@@ -13,9 +13,11 @@ EffectHostParticle::EffectHostParticle(particle::WeakParticlePtr particle, matri
1313 EffectHost(orientationOverride, orientationOverrideRelative), m_particle(std::move(particle)) {}
1414
1515// Particle hosts can never have a parent, so it'll always return global space
16- std::pair<vec3d, matrix> EffectHostParticle::getPositionAndOrientation (bool /* relativeToParent*/ , float interp, const std::optional<vec3d>& tabled_offset) const {
16+ std::pair<vec3d, matrix> EffectHostParticle::getPositionAndOrientation (bool relativeToParent, float interp, const std::optional<vec3d>& tabled_offset) const {
1717 const auto & particle = m_particle.lock ();
1818
19+ relativeToParent &= particle->attached_objnum >= 0 ;
20+
1921 vec3d pos;
2022 if (interp != 0 .0f ) {
2123 float vel_scalar = particle->parent_effect .getParticleEffect ().m_lifetime_curves .get_output (particle::ParticleEffect::ParticleLifetimeCurvesOutput::VELOCITY_MULT, std::forward_as_tuple (*particle, vm_vec_mag_quick (&particle->velocity )));
@@ -25,6 +27,15 @@ std::pair<vec3d, matrix> EffectHostParticle::getPositionAndOrientation(bool /*re
2527 pos = particle->pos ;
2628 }
2729
30+ // We might need to convert the position to global space if the parent particle has a parent
31+ if (particle->attached_objnum >= 0 ) {
32+ vec3d global_pos;
33+ vm_vec_linear_interpolate (&global_pos, &Objects[particle->attached_objnum ].pos , &Objects[particle->attached_objnum ].last_pos , interp);
34+
35+ vm_vec_unrotate (&pos, &pos, &Objects[particle->attached_objnum ].orient );
36+ pos += global_pos;
37+ }
38+
2839 // find the particle direction (normalized vector)
2940 // note: this can't be computed for particles with 0 velocity, so use the safe version
3041 vec3d particle_dir;
@@ -34,8 +45,20 @@ std::pair<vec3d, matrix> EffectHostParticle::getPositionAndOrientation(bool /*re
3445 pos += particle_dir * tabled_offset->xyz .z ;
3546
3647 matrix orientation;
37- // As there's no sensible uvec in this particle orientation, relative override orientation is not that sensible. Nonetheless, allow it for compatibility, or future orientation-aware particles
38- orientation = m_orientationOverrideRelative ? m_orientationOverride * *vm_vector_2_matrix_norm (&orientation, &particle_dir) : m_orientationOverride;
48+
49+ if (!relativeToParent) {
50+ // As there's no sensible uvec in this particle orientation, relative override orientation is not that sensible. Nonetheless, allow it for compatibility, or future orientation-aware particles
51+ orientation = m_orientationOverrideRelative ? m_orientationOverride * *vm_vector_2_matrix_norm (&orientation, &particle_dir) : m_orientationOverride;
52+ }
53+ else {
54+ // The position data here is in world space
55+ // Since we're operating in local space, we can take the orientation override at face value if it's relative, but we need to convert it from global to local otherwise.
56+ matrix global_orient_transpose;
57+ orientation = m_orientationOverrideRelative ? m_orientationOverride : m_orientationOverride * *vm_copy_transpose (&global_orient_transpose, &Objects[particle->attached_objnum ].orient );
58+
59+ vm_vec_sub2 (&pos, &Objects[particle->attached_objnum ].pos );
60+ vm_vec_rotate (&pos, &pos, &Objects[particle->attached_objnum ].orient );
61+ }
3962
4063 return { pos, orientation };
4164}
@@ -44,6 +67,11 @@ vec3d EffectHostParticle::getVelocity() const {
4467 return m_particle.lock ()->velocity ;
4568}
4669
70+ std::pair<int , int > EffectHostParticle::getParentObjAndSig () const {
71+ const auto & particle = m_particle.lock ();
72+ return {particle->attached_objnum , particle->attached_sig };
73+ }
74+
4775float EffectHostParticle::getLifetime () const {
4876 const auto & particle = m_particle.lock ();
4977 return particle->max_life - particle->age ;
0 commit comments