I got no responses to my last thread so I reduced it to the Plugin issue here.
I need some help with a Particle Plugin I adapted. It works fine so far but one additional feature would be nice and for that I’d like some input from advanced coders.
I am planning to do a hittest between the position coordinates of the Plugin particles and some quads. Now when there’s a collision I want the involved particle to be killed.
My current idea is to feed the plugin with the ‘Point Hit’ pin of the hittest node and set the particle age to a high number when ‘Point Hit’ equals 1.
Would that be possible? If not which other way is advisable?
Here’s the Plugin code:
- region usings
using System;
using System.ComponentModel.Composition;
using System.Collections.Generic;
using VVVV.PluginInterfaces.V1;
using VVVV.PluginInterfaces.V2;
using VVVV.Utils.VColor;
using VVVV.Utils.VMath;
using VVVV.Utils.Animation;
using VVVV.Core.Logging;
- endregion usings
namespace VVVV.Nodes
{
#region PluginInfo
[PluginInfo(Name = "MyBullet", Category = "Animation")](PluginInfo(Name = "MyBullet", Category = "Animation"))
#endregion PluginInfo
public class AnimationMyBulletNode : IPluginEvaluate
{
#region fields & pins
[Input("Input")](Input("Input"))
ISpread<Vector3D> FInput;
[Input("VelocityField")](Input("VelocityField"))
ISpread<Vector3D> FVelocityField;
[Input("Shoot", IsSingle = true)](Input("Shoot", IsSingle = true))
ISpread<bool> FShoot;
[Input("Max Lifetime", IsSingle = true)](Input("Max Lifetime", IsSingle = true))
ISpread<double> FMaxLifeTime;
[Input("Texture Count", IsSingle = true)](Input("Texture Count", IsSingle = true))
ISpread<int> FTexCount;
[Output("Output")](Output("Output"))
ISpread<Vector3D> FOutput;
[Output("Age")](Output("Age"))
ISpread<double> FAge;
[Output("TextureID")](Output("TextureID"))
ISpread<double> FTexIDOut;
[Import()](Import())
ILogger FLogger;
[Import()](Import())
IHDEHost FHDEHost;
List<Particle> FParticles = new List<Particle>();
List<double> FTexIDs = new List<double>();
Random FRandom = new Random();
#endregion fields & pins
//called each frame by vvvv
public void Evaluate(int SpreadMax)
{
//update particles and remove timed out particles
for (int i = FParticles.Count - 1; i >= 0; i--) {
if (!FParticles[i](i).Update(FHDEHost.GetCurrentTime())) {
FParticles.RemoveAt(i);
FTexIDs.RemoveAt(i);
}
}
//add new particles and generate random TextureID
if (FShoot[0](0)) {
FParticles.Add(new Particle(FHDEHost.GetCurrentTime(), FMaxLifeTime[0](0), FInput[0](0), FVelocityField[0](0)));
FTexIDs.Add(FRandom.Next(0, FTexCount[0](0)));
}
//set outputs
FOutput.SliceCount = FParticles.Count;
FAge.SliceCount = FParticles.Count;
FTexIDOut.SliceCount = FParticles.Count;
for (int i = 0; i < FParticles.Count; i++) {
FOutput[i](i) = FParticles[i](i).Position;
FAge[i](i) = FParticles[i](i).Age;
FTexIDOut[i](i) = FTexIDs[i](i);
}
}
}
}
If you want to kill particle on quad hit, you can add a “Kill Particle” bang, then just use the hittest/framedelay combination to notify particles to be killed. Make sure you kill hit particles prior to emit new ones.
I just figured out the first step by adding a Pointhit input to the plugin and extending the if statement which is responsible for removing the particles from the list.
If I start more than one particles now they’re all removed as soon as the first collision occurs. How can I avoid that?
Here’s the new code:
- region usings
using System;
using System.ComponentModel.Composition;
using System.Collections.Generic;
using VVVV.PluginInterfaces.V1;
using VVVV.PluginInterfaces.V2;
using VVVV.Utils.VColor;
using VVVV.Utils.VMath;
using VVVV.Utils.Animation;
using VVVV.Core.Logging;
- endregion usings
namespace VVVV.Nodes
{
#region PluginInfo
[PluginInfo(Name = "MyBullet", Category = "Animation")](PluginInfo(Name = "MyBullet", Category = "Animation"))
#endregion PluginInfo
public class AnimationMyBulletNode : IPluginEvaluate
{
#region fields & pins
[Input("Input")](Input("Input"))
ISpread<Vector3D> FInput;
[Input("VelocityField")](Input("VelocityField"))
ISpread<Vector3D> FVelocityField;
[Input("Shoot", IsSingle = true)](Input("Shoot", IsSingle = true))
ISpread<bool> FShoot;
[Input("Max Lifetime", IsSingle = true)](Input("Max Lifetime", IsSingle = true))
ISpread<double> FMaxLifeTime;
[Input("Texture Count", IsSingle = true)](Input("Texture Count", IsSingle = true))
ISpread<int> FTexCount;
[Input("Point Hit")](Input("Point Hit"))
ISpread<int> FPointHit;
[Output("Output")](Output("Output"))
ISpread<Vector3D> FOutput;
[Output("Age")](Output("Age"))
ISpread<double> FAge;
[Output("TextureID")](Output("TextureID"))
ISpread<double> FTexIDOut;
[Import()](Import())
ILogger FLogger;
[Import()](Import())
IHDEHost FHDEHost;
List<Particle> FParticles = new List<Particle>();
List<double> FTexIDs = new List<double>();
Random FRandom = new Random();
#endregion fields & pins
//called each frame by vvvv
public void Evaluate(int SpreadMax)
{
//update particles and remove timed out particles
for (int i = FParticles.Count - 1; i >= 0; i--) {
if (!FParticles[| (FPointHit[0](i](| (FPointHit[0](i).Update(FHDEHost.GetCurrentTime()) ) == 1)) {
FParticles.RemoveAt(i);
FTexIDs.RemoveAt(i);
}
}
//add new particles and generate random TextureID
if (FShoot[0](0)) {
FParticles.Add(new Particle(FHDEHost.GetCurrentTime(), FMaxLifeTime[0](0), FInput[0](0), FVelocityField[0](0)));
FTexIDs.Add(FRandom.Next(0, FTexCount[0](0)));
}
//set outputs
FOutput.SliceCount = FParticles.Count;
FAge.SliceCount = FParticles.Count;
FTexIDOut.SliceCount = FParticles.Count;
for (int i = 0; i < FParticles.Count; i++) {
FOutput[i](i) = FParticles[i](i).Position;
FAge[i](i) = FParticles[i](i).Age;
FTexIDOut[i](i) = FTexIDs[i](i);
}
}
}
}
I think the way I managed to take the first step now is quite similar to your suggestion. I think the fact that now every particle disappears as soon as there’s a collision has something to do with your statement ^quote:vox:
Make sure you kill hit particles prior to emit new ones.
^
What do you mean by that in terms of coding? How do I set priorities?