Influencer-based ParticleEmitter candidate (mesh-based animated particles)

@t0neg0d said: Actually... no... I have an enum that *will* consist of:

Simple,
Sphere,
Hemisphere,
HugeAssShapedEmitter (etc, etc),
Custom

=) It just doesn’t atm.

And the setMesh setShape thing was a typo… sorry!!

Seems like maybe another good place for a strategy pattern. I haven’t looked at the code, though. I don’t know why an enum is needed instead of just having an object that does the emitting.

1 Like

Random point on a face:

I need the min/max values of x, y and z from the three vectors of the triangle… and then randomFloat*(max-min)

This will give me a random point withing the confines of the face? Correct?

1 Like
@pspeed said: Seems like maybe another good place for a strategy pattern. I haven't looked at the code, though. I don't know why an enum is needed instead of just having an object that does the emitting.

I need a way for the user to be able to either select a default mesh (one generated for them) or use some imported model, custom mesh, etc. If this is not part of the constructor (which I don’t think it should be… seeing as there are initialization params for even a triangle (like size), then this will go away as well. For the time being… it gives me a quick way to test without altering more than a line of code.

1 Like

Taking a step back… what is the life cycle of a particle?

I imagine it to be something like:
-random chance for particle
-random starting location
-create particle
-influence over and over until dead
-remove particle.

Something like that?

1 Like
@t0neg0d said: I need a way for the user to be able to either select a default mesh (one generated for them) or use some imported model, custom mesh, etc. If this is not part of the constructor (which I don't think it should be... seeing as there are initialization params for even a triangle (like size), then this will go away as well. For the time being.. it gives me a quick way to test without altering more than a line of code.

Whether you pass an enum value or a SomeClass.createMe() seems irrelevant in that context. But again, I haven’t looked at the code.

2 Likes
@pspeed said: Taking a step back... what is the life cycle of a particle?

I imagine it to be something like:
-random chance for particle
-random starting location
-create particle
-influence over and over until dead
-remove particle.

Something like that?

This completely depends. Are you emitting particles? Or generating leaves on a tree?

One is finite… the other lasts the duration of the emitter itself.

The emitter can be used for either.

1 Like
@t0neg0d said: This completely depends. Are you emitting particles? Or generating leaves on a tree?

One is finite… the other lasts the duration of the emitter itself.

The emitter can be used for either.

What does the life cycle look like in the grass/leaves case? Do you still apply influencers but just do it once?

1 Like
@pspeed said: What does the life cycle look like in the grass/leaves case? Do you still apply influencers but just do it once?

Actually… this is the coolest part of the emitter. You influence static particles as well.

For instance:

Leaves are billboarded Velocity_Z_Up (top of the texture facing the direction of velocity).
At this point you can use an influencer to sway the leaves in the wind, by altering the velocity and the stem will remain in it’s static point appearing to be attached to the tree.

This works with animated models as well… so you could have fur or hair that is effected by wind but still remains anchored to the model appropriately even as it interpolates between keyframes.

EDIT: I hope this also answered the life-cycle question for static particles

1 Like
@t0neg0d said: Actually... this is the coolest part of the emitter. You influence static particles as well.

For instance:

Leaves are billboarded Velocity_Z_Up (top of the texture facing the direction of velocity).
At this point you can use an influencer to sway the leaves in the wind, by altering the velocity and the stem will remain in it’s static point appearing to be attached to the tree.

This works with animated models as well… so you could have fur or hair that is effected by wind but still remains anchored to the model appropriately even as it interpolates between keyframes.

EDIT: I hope this also answered the life-cycle question for static particles

So the only difference is that static particles don’t die?

How is death determined normally? (Sorry for being thick.)

1 Like

…and how does fur anchoring to animated model work? Is the an influencer that knows the mesh?

1 Like
@pspeed said: ...and how does fur anchoring to animated model work? Is the an influencer that knows the mesh?

Question from previous post:

Life cycle is tracked exactly as it is in the current emitter. Random life cycle duration between min and max (or fixed if both are the same) and decrements each update.

For this question:

A triangle of the mesh is randomly selected and the index of the face is stored with the particle. At any point, the triangle can be retrieved… if the mesh is animated, the position and normal has been recalculated, so you just query the triangle to get the data for updating the particle position as well.

This brings up the need to traverse a mesh and do some minimal categorizing for face size to weight coverage. But that can happen later… and is a one time cost as the emitter is created.

1 Like

I should also mention, that initial velocity vector is determined by the face normal and force. If there is no force, the velocity is a direction only.

1 Like

Ugh… to answer the second portion of the question. Yes, this is handled by an influencer… but it is part of the gravity influencer atm and shouldn’t be. It will have to find a new home before this is finalized.

1 Like

So, in theory, a strategy pattern approach with full flexibility would look something like the following: (And forgive me if it is already this way but the discussion thus far made me think it wasn’t):

[java]
interface ParticleFactory {
Particle createParticle();
}
interface ParticleSource {
void setupParticle( Particle p );
}

if( should create a particle ) {
Particle p = factory.createParticle();
source.setupParticle§;
addParticle§;
}

for( Particle p : particles ) {// or whatever
for( Influencer in : influencers ) {
in.influence(in);
}
if( particle is dead ) remove it.
}
[/java]

It occurs to me that ParticleSource (or whatever, could be ParticleConfig, too) could be a different set of Influencers but it felt like in the case where you are associating it with a triangle that you might want to use the same object as both source (where to put the particle initially) and influencer (where to put the particle over time).

With that approach you could potentially create any kind of particle with any kind of positioning scheme. For example, a user could swap out the plain mesh scheme for one that only uses the triangles that point up (like for fire, grass, etc.). You don’t have to have preconfigured and guessed every emitter type up front… though you could still support the standard ones easily.

1 Like
@t0neg0d said: Random point on a face:

I need the min/max values of x, y and z from the three vectors of the triangle… and then randomFloat*(max-min)

This will give me a random point withing the confines of the face? Correct?

No, it won’t. It will give you a random point inside the bounding axis aligned box of the triangle.

I don’t know how many ways there are but the first way that occurs to me is:
points p1, p2, p3.
random point r = p1 + rand(p2-p1)+rand(p3-p1)

Where rand() calculates a value from 0 to x, 0 to y and 0 to z for each part of a passed in vector and returns the result.

(Replace + by addLocal, insert storage vec3f, whatever as required).

2 Likes
@zarch said: No, it won't. It will give you a random point inside the bounding axis aligned box of the triangle.

I don’t know how many ways there are but the first way that occurs to me is:
points p1, p2, p3.
random point r = p1 + rand(p2-p1)+rand(p3-p1)

Where rand() calculates a value from 0 to x, 0 to y and 0 to z for each part of a passed in vector and returns the result.

(Replace + by addLocal, insert storage vec3f, whatever as required).

Which gets you a point inside a parallelogram where two of the sides are p2-p1 and p3-p1, I think.

1 Like

Yes, you are right. I was hoping to avoid the 3rd check but I think its needed:

rand(p1, p2) gives a random point along the line between p1 and p2.

r = (rand(p1, p2)+rand(p2,p3)+rand(p3,p1))/3 gives a random point inside the triangle but I don’t know how even the distribution will be…

1 Like

2 rands are for sure enough. It linear combination of two vectors. Your original idea was ok, just need to make sure you don’t overshoot the triangle

1 Like

Sorry for the delay in response on this.

I updated the Emitter to allow me to see a wireframe representation emitter shape and particles separately.

I’m definitely overshooting the area and will give @zarch 's suggestion a go (I wasn’t sure how this translated to 3D… thus the stupid questions and alternate idea for a solution).

I need to generate the random offset as if the triangle started at 0,0,0 and then store this info with the particle. This way the offset can be reapplied when the animated mesh updates translation. Anyone have any clue what order the 3 Vector3f (triangle points) are stored in? get1() get2() get3() are a little ambiguous… and it is kinda important to know what is what.

1 Like

The order doesn’t actually matter so long as its the same each time…which it will be.

I’d just use the order they are defined in the index buffer…

1 Like