FX Builder : cloning & save/load capsule support

@normen said: Why can't the emitter grab the mesh at runtime? I mean at some point it will have to be loaded anyway?

When you say runtime, do you mean when the emitter is added to the scene, as apposed to when it is created? That’s a neat idea. I’ll need to update a bit of code… mostly revolving around how the particle relates back to the emission face/point of emission to reset this without having to reinitialize the particle mesh. Unfortunately, there are some components that will force particle reset (not recreation, just refresh), which restarts the emitter visually, anyways and there are a few that force recreation.

At the moment, swapping emitter shapes forces a recreation, as I didn’t expect to have people swapping this out on the fly (i.e. a simple point/triangle emitter for a loaded asset that is animated, etc)

@t0neg0d said: So, in the end, you will export the project to j3o, move the j3o to your project, load it, potentially clone it per instance and call execute to run the sequence of events to reproduce the effect you build.
That's great !
1 Like
@t0neg0d said: When you say runtime, do you mean when the emitter is added to the scene, as apposed to when it is created? That's a neat idea. I'll need to update a bit of code... mostly revolving around how the particle relates back to the emission face/point of emission to reset this without having to reinitialize the particle mesh. Unfortunately, there are some components that will force particle reset (not recreation, just refresh), which restarts the emitter visually, anyways and there are a few that force recreation.

At the moment, swapping emitter shapes forces a recreation, as I didn’t expect to have people swapping this out on the fly (i.e. a simple point/triangle emitter for a loaded asset that is animated, etc)

Basically, yes. Its the nice thing about Controls, they initialize in read() and then have access to the scenegraph to do whatever they’re supposed to do just as if they were attached manually. Btw if you would save the sword model with the effects then the mesh would still be the same shared instance after restoring if you use the jme serialization for everything.

1 Like
@normen said: Basically, yes. Its the nice thing about Controls, they initialize in read() and then have access to the scenegraph to do whatever they're supposed to do just as if they were attached manually. Btw if you would save the sword model *with* the effects then the mesh would still be the same shared instance after restoring if you use the jme serialization for everything.

How is this effected by a change in directory structure?

Does it require resaving? Or does using AssetKey’s in place of String paths solve this issue?

And… this is a prime example of why an SDK plugin would be preferable… wish I knew how, but this project is a great test bed if nothing else.

It’s easy to rapidly develop complex UI’s, and could be used as a model for the other… so, even if it does end up an SDK plugin eventually (if I can ever figure out how to do this), this will make it much easier.

@t0neg0d said: How is this effected by a change in directory structure?

Does it require resaving? Or does using AssetKey’s in place of String paths solve this issue?

It depends on what you do. Images and things like j3m files (stuff that is an actual asset with a path) are the main issue here. So you cannot have a j3o with materials pointing to textures at “Textures/MyImage.jpg” and later put the textures elsewhere. AssetKeys are basically defined by their path and name, just like classes are. Theres no “relative relations” like with filesystems, its more like a classpath. You can move the j3o itself however, as long as its linked files stay in place.

Doing a special plugin would be no problem at all. But I guess just having editors for the bean properties of your Control would already help a lot. Then you could add and edit the Controls in the SDK right away. Any primitives and default jme values (String, int, Enums, Vector3f etc) would be picked up but for special objects or lists you’d need to make an editor for that property (which is only one class really).

I do outline some stuff here: https://wiki.jmonkeyengine.org/legacy/doku.php/sdk:development

2 Likes

I’m hitting an issue with reading & writing the Emitter itself. I understand what the issue is, I’m just a little iffy on the way it would need to be done, as it is a semi-hack.

To save and properly load this, the constructor needs to be void of paramters.
Which requires wrapping the control inside another control that is transparent to the user.
I verified that this is this case (looking at how the current emitter is handled)

My issue is… this is ugly =( And quite confusing to anyone reading the code.

My other option is to change how the the emitter is constructed all together, using an empty constructor and leveraging the initParticles method to create the entire control.

initParticles has to be called anyways… or at least it currently does. Maybe I can figure out a way to wrap this into a generic create() method or something.

Anyways, can I get a few opinions about the best way to proceed with this? I don’t like how the current JME emitter handles this at all. It looks like it is a retrofit for import/export. I DO like the fact the the user is unaware of it… but it makes reading the code really confusing, until you understand why it is there in the first place.

Thoughts for alternatives that I may not have considered?

The empty constructor would really only be used when read() is used to construct the control. So if you manage to write() all information that the user might supply via the constructor then you can re-assign it in read() and just “play as if” the user used the constructor, doing everything thats needed. For adding controls with constructor parameters in the SDK you’d use a wizard, if they cannot be designed without a constructor (e.g. by adding the data afterwards and making the Control handle no data gracefully). Idk if that helps but I adopted your “throw at the wall” approach :wink:

1 Like
@normen said: The empty constructor would really only be used when read() is used to construct the control. So if you manage to write() all information that the user might supply via the constructor then you can re-assign it in read() and just "play as if" the user used the constructor, doing everything thats needed. For adding controls with constructor parameters in the SDK you'd use a wizard, if they cannot be designed without a constructor (e.g. by adding the data afterwards and making the Control handle no data gracefully). Idk if that helps but I adopted your "throw at the wall" approach ;)

This is actually very helpful. Write is working properly from the top down, it just became a problem when reading back in because the Emitter constructor requires 3 parameters.

So, I’ll likely convert this to something along the lines of:

Emitter e = new Emitter();
e.setAllTheFunkyParams(x,y,z); // etc
e.create();

Or something along these lines to bypass the need for a control that controls the control like in the current emitter. The way it is done is cool… especially considering it was likely added after input/output was implemented and it also accounts for some change that was made to the control’s control and old save files. It just makes reading the code confusing.

Actually, scratch that. The emitter is a control. Initialize … not .create()

Well… it works well.

/forehead slap - I forgot control = setSpatial… not initialize

So, I had to add an an initialize(assetManager); method… but, there were some other added benefits to doing this, aside from the empty constructor. The main one being, the ability to dynamically alter the max particle count. It’s an expensive process, however, it recreates the ParticleData array and then maps the current state of each live particle to where it is currently. So there is not reset of the emitter when you alter the maximum particle count.

This happens seemlessly when the max particle count is raised. On the other hand if you set it smaller than the original, it maps every particle it can and the excess are removed.

The only time there is a noticable stutter is when your particle count is high and your using a complex mesh as a particle template.

I’m hoping to be able to do the same for altering influencer steps for any that offer multiple stages (like color, size, destination, etc)… though, this is a little trickier.

1 Like

Saving to/loading from j3o is working fine… except >.<

emissionsPerSecond and particlesPerEmission seem to be set properly, however the emitter looks like it is pushing all particles at once every cycle. It’s something simple I’m overlooking between the way clone works and this reloads the saved emitter.

I was truly expecting a problem in something a little bit more complex than this… like the hack for storing arrays of Interpolation(s) which is not and never will be a Savable (as far as I can tell anyways).

Anyways… simple issue that I’ll get resolved soon.

Then I should be able to apply this to the builder’s project as a single Control.

EDIT: Yep… silly mistake on my part. I need to take a day or two to fully test save/load by adding it to the builder so I can test all possible scenarios.

1 Like

There have been quite a few updates for the emitter system and will upload the updates this evening. These may not be completely reflected in the builder right away, but will be soon.

Here is a list of the updates:

  • Lighting! Particle lighting updates properly now
  • Color and Alpha support for all Materials that support Vertex Colors
  • Emitter & Particle animation is now an internal function to the emitter - The process of setting this up externally could potentially cause confusion, due to what was involved in getting this to work.
  • Internal animation handling is exported with the saved j3o so when the emitter is reloaded all emitter & particle animations are reconstructed properly and load with the defined animations already playing.
  • The single catch to this is emitter shapes that point at in-game assets, but can be properly reset by calling setParticleType again with the Node contained in your scene. Otherwise, the loaded emitter shape is not sync’d to the asset in your scene–unless the entire scene was saved at the same time.

More on animation:

  • When defining the emitter shape, you pass in the Node containing the mesh as apposed to the Mesh itself if you wish to have the emitter handle animations for you.
  • If the emitter shape is not already a model within your scene, a method is provided for setting the animation, otherwise the animation is automatically sync’d to your game asset.
  • When defining a particle template, you pass in the Node containing the mesh as apposed to the Mesh itself if you wish to have the emitter handle animations for you.
  • Particle animation is separate from scene assets, as there is no need that I could foresee where the particles would mimic an in-scene asset always. - This is subject to change if someone can provide a use case =) EDIT: The one and only use case I can come up with is Magic Mirror from AD&D… buuut… is this the best way of producing that effect? It actually very well might be.

I still have some testing to do with point-based particles and would LOVE IT if someone could point me at the test for soft particles, as I am retarded and haven’t found it and haven’t been able to get it working. There is a boolean you set in the Particle.j3md but this seems to do nothing (whether I set softness or not). There must be more involved

1 Like
@t0neg0d said: * Particle animation is separate from scene assets, as there is no need that I could foresee where the particles would mimic an in-scene asset always. - This is subject to change if someone can provide a use case =) EDIT: The one and only use case I can come up with is Magic Mirror from AD&D... buuut... is this the best way of producing that effect? It actually very well might be.
Huh? I don't get what you mean by "separate from scene assets"?

Oh, and do you mean jme3test.effect.TestSoftParticles?

@normen said: Huh? I don't get what you mean by "separate from scene assets"?

Oh, and do you mean jme3test.effect.TestSoftParticles?

Well… you can use an asset that is already in your scene as an emitter shape, this way nothing extra is loaded, it just points at the already existing mesh. So when you set an animation on the node of your in-game asset the emitter shape is automatically transformed accordingly (because they are the same thing). If the emitter shape doesn’t exist in your scene, it has to be loaded and managed separately.

With particle templates, I’m assuming right now you don’t have the asset in your scene already, so it loads the template and manages animations internally to the emitter. Changing this to allow it to work the way emitter shape does is as easy as adding a flag… I just couldn’t think of enough use cases and wanted to see if anyone else thought it was necessary.

And thanks for the test file. I couldn’t figure out how to get this working.

@t0neg0d said: Well... you can use an asset that is already in your scene as an emitter shape, this way nothing extra is loaded, it just points at the already existing mesh. So when you set an animation on the node of your in-game asset the emitter shape is automatically transformed accordingly (because they are the same thing). If the emitter shape doesn't exist in your scene, it has to be loaded and managed separately.

With particle templates, I’m assuming right now you don’t have the asset in your scene already, so it loads the template and manages animations internally to the emitter. Changing this to allow it to work the way emitter shape does is as easy as adding a flag… I just couldn’t think of enough use cases and wanted to see if anyone else thought it was necessary.

And thanks for the test file. I couldn’t figure out how to get this working.

Right, I see… If you would store the emitter shape in an external j3o file and use an AssetLinkNode to save in the emitter… Then when that external j3o is loaded a second time (no matter if by your emitters or the actual scene) the assetManager will share it automatically…

Otherwise yes, even if you would share the mesh initially, if the original isn’t saved along with it it in the same scene, loading that mesh a second time would then instantiate it a second time as the link is broken.

Soft particles implies passing the depth buffer to the particle material, so it involves post processing in a way… For now I hacked it in to the translucentBucket filter but it needs a bit more thinking

@t0neg0d said: Did everything run ok after this?

I’ve spent some more time with EmitterBuilder and figured out how to do some cool things. It’s fairly intuitive.

I wish I didn’t have to keep clicking on text boxes, typing numbers, and clicking on right-pointing triangles. It slows down my experimentation and tuning. Could you use controls that don’t require so much back-and-forth between the keyboard and the mouse, such as sliders/trackbars?

Actually the “scripts” feature could fit in the EffectTrack system that we have in JME. It’s basically the same idea "Emmit at for ", the number of particle is not supported, but could easily be added.
The main advantage would be that you would be able to attach your particle emitter script to another geometry animation. and go myOtherGeom.getControl(AnimControl.class).createChannel().setAmin(“theAnimIHaveMyEmitterTiedTo”);

Think of puffs of dust rising from the feet of a character in a walk animation.
I know you went the control route, as I suggested, but now that I’ve seen the actual fx builder and wrapped my head around it, well the track route seems better… :stuck_out_tongue:

I’m really impressed by the visual effects you can get with a couple of basic textures…

1 Like
@nehon said: Actually the "scripts" feature could fit in the EffectTrack system that we have in JME. It's basically the same idea "Emmit at <time> for <time>", the number of particle is not supported, but could easily be added. The main advantage would be that you would be able to attach your particle emitter script to another geometry animation. and go myOtherGeom.getControl(AnimControl.class).createChannel().setAmin("theAnimIHaveMyEmitterTiedTo");

Think of puffs of dust rising from the feet of a character in a walk animation.
I know you went the control route, as I suggested, but now that I’ve seen the actual fx builder and wrapped my head around it, well the track route seems better… :stuck_out_tongue:

I’m really impressed by the visual effects you can get with a couple of basic textures…

I’m open to whatever works best. Can’t say I would be capable of making it happen! But, since the source is available now, and multiple smart people can figure out what needs to change to sum up a more final version of the emitter, I can just add those needed to the list of project contributors/owners/whatever, or the source code can be moved to a repo that you devs control and changed as needed.

I think I’ve added most of what I saw as a basic at a minimum, this should be able to’s and it can be managed however you all see fit from here.

The FX builder was really put together so I could test the hell out of the emitter…