Particle System Revamp

I used several different emitter shapes in the test file already. I still need to add one that uses the mesh emitter. I didn’t show it in the video, but there is a debug setting that will show the emitter shape. I mostly kept that naming convention because that is what the existing system uses. I do probably need to at least add “shape” to the name to better delineate what they are. At the moment you would just assume that it is a type of emitter.

Well right now you don’t need to feed time into the emitter because it gets updated by normal scene graph operations. The existing tweens don’t use tpf which would be needed to update the emitter.

I could think of a couple of effect tweens that would make sense to add. Stuff like emitting all particles or small group of particles. You could do something that emits a few dust particles for example every time a characters foot touched the ground or when a character lands from jumping.

So what has thrown be off about tweens is that usually there is a 1 to 1 mapping between tweens and what you are effecting. It’s a little different when you have thousands of particles that all have different time values. I could MAYBE use the tweens CurveFunction but it’s not clear to me how to make tweens themselves work with it in a way that is clean. I’m open to redesigning the systems if there is a good design i’m missing.

In a similar way, influencer can’t really be replaced by tweens as is because you need the tpf value in a lot of them.

1 Like


I added this to the tests you can cycle through. I still need to add one for emitting meshes as particles.

2 Likes

I mean if it is going to be tween based it should get the time from the tween, not from the scene graph. If emitter needs “tpf” it can calculate it from the time provided by tween. Note that we can fast-forward tween, we can pause tween, we can play tween backward so they need to be reflected into emitter influencers.

Pretty cool stuff @glh3586 - nice work.

this looks better and better. :slight_smile:

That just sounds like it would add a lot of complexity to what is a pretty straightforward design. It also really complicates more complex influencers like particle trails. I’m not sure what exactly is gained by that.

Part of what i’m missing is that tweens seem to have a 1 to 1 design. For every particle there would have to be a tween for each change (which would also drastically increase the memory needed). Otherwise you would have to do something funky like:

class ColorInfluencerTween implements Tween {

  private ParticleData currentParticle;
  private ColorRGBA startColor = new ColorRGBA(1, 0, 0, 1.0f);
  private ColorRGBA endColor = new ColorRGBA(0, 1, 0, 1.0f);
  
  public void setCurrentParticle(ParticleData particle) {
    currentParticle = particle;
  }
  
  @Override
  public double getLength() {
    return currentParticle.life;
  }

  @Override
  public boolean interpolate(double t) {
    currentParticle.color.interpolateLocal(startColor, endColor, (float) t);
    return false;
  }
}

It’s even more broken if you just pass the emitter or particle data to the tween as well. It also gets further complicated once you start interacting with other objects with physics. How can you play a tween backwards on an emitter if a collision object has changed position? How do you figure out what particles have died to rewind them and where they died?

1 Like

Yes, I see the complexity. So if emitter time supposed to be independent of tween, then I guess a CallMethod tween would be enough to integrate with the new animation system.

So we just need to pass emitter object with the appropriate method name to activate it and done. :slightly_smiling_face:

To make my point clearer, influencers and tweens are doing different things.

But if you are animating something over time like particle count, or a color shift, etc. that’s where it would be nice to control those parameters with tweens because then they can be composed with any number of other animations.

I’m not sure i’m understanding what you are getting at. I mean changing the particle count would be as easy as:

new CallMethod(emitter, "setParticleCount", 500);

Edit: Accidentally hit enter there. Changing the color is currently a function of influencers as well. Could you give more examples perhaps? The only thing that looks like I could pull from is the curve function inside the tweens class at the moment.

I think we are thinking of two different kinds of color change. You are talking about this one that changes the color of a specific particle over time.

I was talking about the case where you want to change the color of the emit particles over time. Or the size, frequency, etc… Edit: it occurs to me that this still might not be clear… but imagine first you emit blue particles that shift to emitting red particles over time. The particles themselves fade individually but their color is set at the start by a starting color controlled by a tween.

And yes, CallMethod is fine (though not the way you have it since that wouldn’t actually ‘tween’ at all) but it’s also tedious for common things.

Edit 2: and note that it could also be super tempting to abuse influencers to do this same thing… which is what discussing this should hopefully avoid.

I see what you are getting at now. You can already animate the emit color / size / start speed over time with the existing system. All of the “start” params are just like any of the particle attribute. The start parameters, however, use the emitter’s internal duration. By default the emitter cycles / loops but you could set an emitter to only emit for like 10 seconds and over time the particle start color would change from red to green. Pretty much any parameter on the emitter that makes sense to change over time works like that. It’s one of the things that I pulled from how unity treat’s their emitters. For example:

float blendAmount = emitter.getCurrentDuration() / emitter.getDuration();
float minLife = lifeMin.getValue(blendAmount, randomValue);
    startlife = (lifeMax.getValue(blendAmount, randomValue) - minLife) * FastMath.nextRandomFloat() + minLife;
startSize = emitter.getStartSize().getValue(blendAmount, randomValue);
emitter.getStartRotation().getValue3f(blendAmount, randomValue, angles);
emitter.getStartColor().getValueColor(blendAmount, randomValue, startColor);

The random value is used for when the value type is supposed to be “random” between two curves.

This isn’t on an influencer, but is there a problem you see with that design?

The CallMethod is a bad example because it’s one of the few attributes that I don’t let change over time since you would have to rebuild the particle mesh. I was just using it as an example of something you could do in concert with some sort of other animation.

I think these are probably the things that people would encourage you to make tweens so that they would/could integrate with the other animations. I don’t know what that means, exactly.

Tweens are composable and can operate over more than just time. (For example, a tween could be controlled by a slider or be part of the slider, etc…) Like, imagine a spark emitter that emits blue but when dragged up shifts from red through to yellow/white as it gets higher. Tweens are setup to do things like that since they are sort of 0-1 based… time/duration are supplied externally for time-based animations.

Okay, that makes sense. I could add some tweens that work on an emitter pretty easily. So something like:

public class ParticleTweens {

  public static Tween startSize(Emitter emitter, double length, float startSize, float endSize) {
    return new ParticleSizeTween(emitter, length, startSize, endSize);
  }

  private static class ParticleSizeTween extends AbstractTween {
    private float startSize;
    private float endSize;
    private Emitter emitter;

    public ParticleSizeTween(Emitter emitter, double length, float startSize, float endSize) {
      super(length);
      this.startSize = startSize;
      this.endSize = endSize;
      this.emitter = emitter;
    }

    @Override
    protected void doInterpolate(double t) {
      emitter.setStartSize(new ValueType((float) (startSize + endSize * t)));
    }
  }
}
1 Like

So maybe to have a specific use case:
The Influencer would be GravityInfluencer and then there would be a Tween changing the Gravity Value of said Influencer (based on time or animation or or or)

@glh3586 Hi, I couldn’t find any examples in your repo, are there any?
BTW it looks nice and I can’t wait to try it out :slight_smile:

I haven’t added the new changes yet but I probably will sometime in the next week. I’ve added a test emitter file in the jme-examples project so you can see some basic effects and usage. I also plan on writing up something for the wiki once the pull request is accepted. The particle system itself is probably done at this point but I am adding a bunch of tweens for people to use.

4 Likes

So i’ve been a bit swamped the last two weeks between my wife’s surgery and a work trip. I had some time to sit down and finish up some of the changes I was working and uploaded an updated copy of my code to github.

I also went through and added some basic tweens for a lot of the Emitter’s “start” values. Specifically:

  • Start Size
  • Life Min
  • Life Max
  • Start Speed
  • Gravity
  • Start Color
  • Emissions

I’m going to let this sit for a few days in case anyone has any other feedback. If not, i’ll submit a pull request.

4 Likes

Would you be interested in writing an article on this for the news page on the new site?

Basically explain your motivation, the benefits, etc…

I feel like this is pretty much exactly the type of thing we need to be documenting so people know what’s changed since they last looked.

1 Like

Sure, I wouldn’t mind doing that. I’m trying to organize my documentation at the moment so i’ll add that to the list :slight_smile:

2 Likes

I didn’t receive any additional feedback so I submitted the pull request :slight_smile:

3 Likes