Custom particle plugin question

The shooter guy again…

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.

Should be it really.

Update.

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);
			}
		}
	}
}

Thanks vux!

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?

They all die due to ^code:
FPointHit0 == 1

should be

FPointHiti == 1
^

for priority, you just do one loop per task, in the order you want.

eg:

  • first loop to destroy hit particles, so you preserve hit result indexes.
  • second loop to process lifetime
  • third loop to emit

Awesome! That was it.
Thanks man.