A particle library that uses 32B / particle without memory fragmentation.

Hi folks,

I’m working on a particle library that you can see in action at http://www.in-poculis.com/partykewl/partykewlEditor.jnlp

It uses 32 bytes per particles and memory is not fragmented because a large FloatBuffer is allocated at the initialization.
Here is how particles are managed:

/*

  • Dead particles:
  •  2 Bytes indicating the position of the next dead particle. 0xffff -> end of list.
    
  • Alive particles:
  • [][] 2 bytes indicating the position of the next alive particle. 0xffff -> end of list.
  • [] 1 bit used to know if this particle is in world space or not
  •      1 bit to know if this particle has already collide with something
    
  •      1 bit unused
    
  •      5 bit for the index of the emitter in the parent generator( to retrieve bases for life, velocity...)
    
  • [] 1 byte for the last update frame. This is a 255 modulo and it just serves for debugging purposes.
  • [][][][] 4 bytes for particle life. This value is updated on each rendering pass.
  • [][][][] 4 bytes seed to regenerate parameters
  • [][][][] 4 bytes for creation position X // Updated on collision
  • [][][][] 4 bytes for creation position Y // Updated on collision
  • [][][][] 4 bytes for creation position Z // Updated on collision
  • [][][][] 4 bytes for compressed direction X, Y, Z // Updated on collision
  • [][] 2 bytes for velocity coefficient // Updated on collision
  • [][] 2 byte for delta life. We have to add this value to the particle life to know
  •      the full elapsed time since the creation of the particle because collision affectors reset
    
  •      the life of particles when they update the particule position and direction.
    

*/

Where are the UV, the color… ?
A seed is stored within each particle. When particles are renderered, we use a home made java random number generator to retrieve values in the range [-1, 1] for each parameter !
Yes, if you know that the first variable is the color, then using the random number generator with the same seed will always return the same value in the range [-1, 1] for your random color. You then use this value in the range [-1, 1] as the seed for a new call to the random number generator to get a new value ( used for the UV this time )…

The method:
public static float nextNormalizedRandom( float p_seed ) {
// Create a random integer with p_seed as a integer.
int l_value=214013*Float.floatToIntBits(p_seed)+2531011;

    // Consider l_value as a float and
    // keep only the mantissa (IEEE 754)
    l_value&=0x007fffff;
    
    // Make the number in the range [2.F, 4.F[ (IEEE 754)
    l_value|=0x40000000;
    
    // Consider the bits of l_value as representing a float
    // then return an adjusted float in the range [-1.F, 1.F[
    return Float.intBitsToFloat(l_value)-3.f;
}

You can do a interesting benchmark: call this method 100 millions times in a C++ for loop ( use a direct cast for Float.floatToIntBits ). VC++ 2005 is 10% slower than java on my computer in release !

More explanations ?
http://www.in-poculis.com/ParticlesPaper_LERAT_STEVENS_2007.doc

Why is the editor so beautiful ?
Because it uses the dev.java.net project: Substance !

Performances ?
10 000 particles per frame at 75hz on an Athlon 64@3.2GHz + GeForce 6600 + 512MB + 17"

By the way, you can add your own affectors and an abstract renderer is present to allow you to use it with another renderer.

My questions:
What do you think of the editor ?
I would like to publish the source as GPL, so is there a best place to publish such a library ?

Cheers,
Bernard.
Advice: The best Sokoban on this earth (Indyo) was registered only one time in 2007 ! Result: the graphist left the team. If you could lend yours to me… or register dozen of copies, maybe that he’ll be back. Thx, http://www.in-poculis.com

Doesn’t work on Solaris/x86. Something is wrong with the jogl.jnlp and/or the copies of the binaries you’ve made locally. It would be better if you would point to the master jogl.jnlp extension on download.java.net.

The exception is


java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.sun.javaws.Launcher.executeApplication(Launcher.java:1272)
	at com.sun.javaws.Launcher.executeMainClass(Launcher.java:1218)
	at com.sun.javaws.Launcher.doLaunchApp(Launcher.java:1065)
	at com.sun.javaws.Launcher.run(Launcher.java:105)
	at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.UnsatisfiedLinkError: no jogl in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1682)
	at java.lang.Runtime.loadLibrary0(Runtime.java:823)
	at java.lang.System.loadLibrary(System.java:1030)
	at com.sun.opengl.impl.NativeLibLoader$DefaultAction.loadLibrary(NativeLibLoader.java:78)
	at com.sun.opengl.impl.NativeLibLoader.loadLibrary(NativeLibLoader.java:101)
	at com.sun.opengl.impl.NativeLibLoader.access$100(NativeLibLoader.java:47)
	at com.sun.opengl.impl.NativeLibLoader$1.run(NativeLibLoader.java:109)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.sun.opengl.impl.NativeLibLoader.loadCore(NativeLibLoader.java:107)
	at com.sun.opengl.impl.x11.X11GLDrawableFactory.<clinit>(X11GLDrawableFactory.java:98)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:169)
	at javax.media.opengl.GLDrawableFactory.getFactory(GLDrawableFactory.java:111)
	at javax.media.opengl.GLCanvas.<init>(GLCanvas.java:113)
	at javax.media.opengl.GLCanvas.<init>(GLCanvas.java:82)
	at javax.media.opengl.GLCanvas.<init>(GLCanvas.java:75)
	at com.inpoculis.partykewl.editor.View3d.<init>(View3d.java:92)
	at com.inpoculis.partykewl.editor.EditorFrame.<init>(EditorFrame.java:116)
	at com.inpoculis.partykewl.editor.Editor.main(Editor.java:57)
	... 9 more

Sorry, it is corrected.

Some features that were not listed:

  • A tool extracts the frames from an animated GIF to put them in a texture. You can then use the UVEvolutionAffector to animate your particles.
  • To move the camera: left click + directional key
  • You can use a heighfield texture to emit particles by using the HeighfieldEmitter

Cheers,
Bernard.

Looks cool. Would be good to allow more interaction in 3D space as opposed to entering values in text fields. See for example the gleem source code in the jogl-demos workspace or the MSG source code in the joglutils workspace for how to do mouse interaction in 3D.

You need a -Dsun.java2d.noddraw=true system property setting in your main JNLP to make things work correctly on Windows.

Are you considering open-sourcing this project?

For the moment, we can move the camera in a Quake like style but I’ll throw a glance at the gleem source code to improve the interaction.

The -Dsun.java2d.noddraw=true is now included in the jnlp.

Yes I’m considering open-sourcing the project, but I have to finish the source code documentation and to translate the editor documentation before. I have a little todo list too, so it will be open-source for the end of september or in october.
Is the best place for open-sourcing such a project is dev.java.net ?

Interesting approach, do you have any performance comparisons with a “normal” particle system (ie. keeping the particle state as regular object variables and pushing them into a float buffer to render). I would have expected that the overhead of getting and updating all the particle data in the float buffer would slow you down unnessesarily.

Unfortunately, I don’t have any performance comparisons with an other java particle system implementation. However, passing -server to the jvm increases the performances of 40%.

I took this approach because the size of particles will always be 32 bytes. If you need a new affector that needs to save data for each particle, the random number generator will do the stuff for 0 bytes of memory. So the basis of the library will be very stable, developpers can create new affectors or emitters without touching the rest of the code.

Also, there is no update() then render() passes. There is only a rendering pass that does the update at the same time that it fills a ParticleDefinition object. This object is passed to the renderer when the rendering method finishes the list of affectors.

So we have very few memory access and cache missed are reduced thankful to the size of the particles.

To finish, the initial position of the particles are stored so you don’t have to render generators that are not visible.

I think java.net is a good choice. It’s been working pretty well for JOGL and related projects.