Custom Datatypes - think ParticleSystem

aaaand number two. the classic particle system. hope everyone can follow. let us know if anything i said in the video requires any additional clarification.


Just about to start watching, but I thought I’d flag audio issues, as they were in the last one too, your mic’s a bit distorted, be good to try and fix that before you do any more… ;)

that’s just joreg’s voice after the weekend… every monday!

but otherwise i cannot hear any distortion and i have pretty nice studio speakers here. at what times in the video are you hearing them? can you check with headphones again and make sure that you haven’t turned any volume over 100%?

Only at the start this time, must have recovered quickly ;)

1 Like

Thanks for the tutorial!

What’s the quickest way to change the particle system to use vec3 not vec2 (ie make 3d) without rebuilding it?

if you looked at the implementation of the particle type, there was no type set anywhere, so the particle works for any type that has a “+” defined (how cool is that?).

in the particle system patch, you just have to change the input types for the Create node to Vector3 and that should be it!

the Random is also adaptive, i changes its type if you connect Vector3 IOBoxes for ‘From’ and ‘To’ to it.

yep it’s super cool :)

ah haa - you need to remove any object that defines that part of the graph(?) as a certain type, then the nodes go light grey, and you can connect the new object of different type.


Nice, queue 2,
take time implement same way in Vl & c#, seems C# faster that VL~~

Many thanks for the Video.
Helps a lot.
Still, did not understand the “pads” thing completely…

you can think of pads like a storage place in memory with a name, aka property or data field. if a link goes into it, it will store the value there. if a link goes out of it it reads the currently stored value. if you have many pads with the same name in the same patch, they all access the same data field.

pads are a way to store data between frames (like FrameDelay + S/R nodes in vvvv):

and since VL has operations, pads have a second purpose which is storing data between operation calls. for example you can store something to it when create is called in order to initialize the data:

or you have another operation HalveValue that halves the current value:

and since pads do not belong to one operation, you can connect links from multiple operations to them. so the above can be patched more succinct and in a more data flow-ish way like this:

you can write into a data field once per operation and read from it as many times as you want. so the point is, all pads with the same name in the same patch are basically the same thing.

Hi tonfilm,

thank you for this great explanation. I think this would perfectly fit into the Graybook.

What i don’t really get is the HalveValue Operation. The links are brown, so it seems not to be executed at the same time as the + Node in the Update. What is confusing to me, is that in the last picture, everything goes into the MyPadName Pad but there must be an order how that happens… Or am i wrong?

The different operations each become separate nodes, so in this example you end up with Create, Update and HalveValue nodes in the nodebrowser (each with a prefix of whatever the above patch is called)

These nodes are what you patch with elsewhere in the VL project to utilise the functionality you defined as operations. The structure in which you patch them defines the order of operation

Thanks @mrboni i think i somehow understood it, but i’m stuck in actually using it.
I played around with the particle system and tried to mix it with thh ConnectAll VL Patch.

Basically what i wanted to achieve is, that if particles are in a certain range they change their color. But i don’t now how to actually update the color.

See the attached Patch: (10.5 KB)

Btw. an option to set the Index of a ForEach section could be useful i think. Now its 0 by default if i’am right or am I missing something?


that is correct. let’s make a little record type called MyIntegrator from the above patch and add one more operation called GetValue that just outputs the value currently stored in the field:

this results in a bunch of nodes that all output and/or input one instance of the integrator. if the nodes are now used in another patch, the dataflow in the patch defines the order of execution:

note that if there would be no HalveValue node, the part of the integrator patch would never be called.

you Particle is just fine, only the construction with the loops and ifs was not correct. and i can totally see why this is complicated. maybe we need to invest more power into documenting accumulators and splicers.

in your patch, i think you tried too many things at once. i cleaned up the patch and gave some elements a description. i have also removed the optimization that tries to update two particles in one go with ‘<’ instead of ‘!=’.

so first only concentrate on one particle called ThisParticle and ‘all others’ to make the path of ThisParticle more clear in the patch. also it is good to separate the steps of collision detection and update mentally… so first collision detection and then update the position because it also outputs the position: (11.3 KB)

Hi Tonfilm,

thanks again for this great explanation.
Looks so easy when you do it :).

Basically this works great but i ran into new issues. Always i think i understood it, there is something not working as expected.
I tried recolour a particle after it is out of range and added another SetColor after the first . So i thought this could be an “else” part. But it is not working. Or at least not as i thought. Now only the last created particle works as expected all other don’t. This is something I ran into quite often since using VL. Either i absolutely dont understand how VL handles ForEach loops or there something different that is missing.

Furthermore what i found out is, that if there will be several particles emitted by feeding the System with more than one starting point (in my case the RandomSpread with a count more than 2) those emitted particles will in VL be handles as 1 Slice in a Spread. But still work as individual particles. It somehow make sende, cause the create operation is just getting called once with a spread of starting points. So it will not be a spread in VL, while in VVVV its a spread.

Questions over questions… (15.8 KB)


the uploaded patch does not resemble your screenshot…was this intended?

you have to be aware that the inner loop runs for ALL OTHER particles. so this means, that if you have an IF/ELSE you will ALWAYS set the color for each distance check. this means you will end up with the color from the last check.

the problem described above is just a very classic everyday programming mistake. done that, been there numerous times. it’s not especially related to VL, it rather comes with all the new programming possibilities.

since this is such a common thing, there is help! you can ‘break’ the ForEach loop as soon as you found a collision. this is also good for performance, because you know that if you found a collision, you don’t have to look further:

and if you know that you will always set the color, you don’t need to put the SetColor in an if region, but input a different color depending on whether particles collide or not:

and the patch: (11.0 KB)

Hi Guys , thanks a lot for this great tutorials , please do more of those wonderfull videos, i see little light on learning vl this way ;D .

I have just done this tut . just a silly thing.

In your patch i see that when you unclick the particles they keep alive but in my patch not when i unclick all (8.0 KB)
. probably something really silly but just in case i missed something.


ai color, above is a screenshot from your patch where you see the bugger:
you see the two diamond inputs of the if-region and their output counterparts. you see how they can be distinguished by their label. one has no label, the other has a simple roman 1 as its label.

by taking the Spread into the if-region via the input labeled I and returning it via the unlabeled output you’re breaking the loop. to fix your example delete the input labeled I and connect the Add node upstream to the Clear node via the unlabeled input.

1 Like