Particle-based fluid simulation

January 15th, 2011
by admin

I’ve recently stumbled upon this paper about fluid simulation – “Particle-based Viscoelastic Fluid Simulation by S. Clavet et. al.

This paper just screams “implement me”, because its content lacks of unnecessary formalism and entire idea of particle simulation is explained with a pseudocode. So all I needed to do is just rewrite the pseudocode into an actionScript code…
So this is the demo:

There are bunch of parameters which controls the fluid properties – this is an advantage of using the particle fluid model.
Make/grab option lets you add the particles, as well as grab them (when clicked in the center of the particle )
Yield ratio influences stickyness or “stretchyness”. The lower the value, the stickiness or “stretchyness” is higher (of course if “sticky” or “stretchy” sliders are nonzero).
“Smooth jitter” and “smooth pulse” smoothes fluid velocity field, “smooth jitter” handles fast velocities and the other handles slow velocities respectively.

There are many possibilities of how to optimize this, mainly PixelBender to calculate the distance field and alchemy to optimize some vector operations. I believe that there exists some tricks to optimize the goo rendering – it’s taking 50% of frame evaluation. Another subjects to optimize:
– highly unoptimized collision system
– getting rid of Vector’s splice function in spring adjusting function
Maybe somebody in the future (most probably – me;p) will “pixelbenderize” this thing, mainly because I’m curious how much faster can it be.

Additionally I’ve written a “library” (1000 lines of code, the “library” term is an exaggeration) which lets you create your own goo, main class of the library is instantiated via
var gg:GooGen=new GooGen( stage.stageWidth , stage.stageHeight );
There is a bunch of methods for adding,deleting particles, and most important – for simulating them:

gg.addParticle( x,y ); // add particle at x,y
gg.step(delta); // one step of simulation
gg.drawParticles(); // renders all particles, since GooGen extends Bitmap class
gg.getParticleAtPos(mouseX,mouseY); // gets particle at x,y
gg.addBody( x,y,width,height,rotation); // adds a wall. avoid adding too many walls, or optimize my code ;p

I don’t believe anyone will try to do something using this class, so I saved myself a trouble of writing any documentation :P Wide programmers will always figure out how to use it from the demo source I’m providing:

demo source
GooGen “lib”

Demo uses (as you can see) bit101’s minimal components.

Posted in flash experiments | Comments (3)

Papervision3D real-time level of detail ( LOD )

July 24th, 2010
by admin

I’ve changed my old quadrics decimation library to make it run in real-time.

Previous quadrics were intended to work with big meshes ( that is over 5000 faces, meshes with such number of faces slows pv3d down very much, and they can’t be used on the web ) and task of decimating such mesh involved converting to my mesh format ( instead of papervision’s TriangleMesh ), decimating and then converting back to TriangleMesh. This type of workflow excluded the possibility of real-time LOD ( for games for example ) because to make LOD work in real time in papervision, we must extend TriangleMesh class and refine geometry that is currently displayed on screen.

New library, “qemlive” depends on HEMesh ( the name comes from Half-Edge mesh because it uses half-edges for adjacency lookup ) class that extends Papervision’s TriangleMesh class and during decimation, HEMesh refines TriangleMesh’es GeometryObject3D. It also remembers everything that was changed during decimation, to effectively revert decimation and come back to the original form of a mesh. To speed-up the decimation process, edge collapses don’t compute new vertex positions, best vertex is chosen among face’s vertices.

Now, the examples ( notice the speed-up in fps )
CYLINDER

CUBE


SPHERE

Here, uv coords and normal’s prevervation ( described further ) was used to preserve spherical shape of the sphere
X-WING
For an x-wing, click HERE

When decimating xwing, uv and normal preservation was used, to preserve two “antennas” in the front of the xwing. The texture mapping breaks down a bit while decimating, this is because there are many discontinuities in xwing’s texture.

All models use almost the same decimation settings, only interpolation method was changed. There are many other settings that changes algorithm’s behaviour… but yah, too lazy to document it. Nobody likes to make a documentation I suppose ; )

The library isn’t public-ready because the code is without documentation and with some debug variables ( as always :p ) but I’ve decided to show the source code, it’s available on googlecode:
http://code.google.com/p/bartekz/source/browse


Zipped qemlive:
http://code.google.com/p/bartekz/downloads/list


Demo source ( not too clean, but the hell … )
http://dl.dropbox.com/u/1268089/QEMLive.as

To instantiate HEMesh, just do this:

var model:HEMesh = new HEMesh( null , null, null , TeleQEM.INTERPOLATE_UV_AND_NORMALS );
model.init( new Sphere( new WireframeMaterial(), 100 , 20 , 20 ) );

See the null’s at the beginning of the constructor? This is one of the reason’s that this library isn’t “public-ready” :p
The fourth parameter controls the way the mesh is decimated ( there are million of other parameters that you can figure out yourself in TeleQEM class ). The possible values are:
TeleQEM.INTERPOLATE_NOTHING – look only at geometry when decimating
TeleQEM.INTERPOLATE_UV – look at uv coordinates during decimation – algorithm tries to preserve correct uv mapping
TeleQEM.INTERPOLATE_UV_AND_NORMALS – look at face normals during decimation as well as uv coordinates – algorithm tries to preserve correct shape of a geometry

We can listen for mesh creation completion:
model.addEventListener( Event.COMPLETE , initComplete );

private function initComplete( e:Event ):void{
do some stuff…
}

To decimate triangles:
model.newqem( model.numFaces*PERCENT_OF_FACES_WE_WANT_TO_LEAVE );

We can set up a listener to listen for decimation completion:

model.addEventListener( TeleQEM.COMPLETE_DECIMATION , decimationCompleted );
private function decimationCompleted( e:Event ):void{
do some stuff…
}

ps. This LOD can be optimized by changing as3’s arrays into vectors. My old decimation algorithm has been made for flash player 9, but the science moves forward … ;) So maybe this will be fixed in the future.

ps2. During “undecimation”, geometry is “forgotten” to free up some memory. If it weren’t, the second decimation could use this fogotten information to decimate the model faster. I think I will make this as an option in HEMesh class in the next update of qemlive – to reuse the decimaton info.

Tags: , , , ,
Posted in flash experiments | Comments (0)

Stupidity

April 12th, 2010
by admin


When something bad happens, you can observe specific emoticons on the internet. Overwhelming amounts of [*]’s which I’m seeing now, has born a demiurge of artistry in me and inspired me to make this >>enormously highly artistic piece of high end artsy art<<

I called it “stupidity” ;)

Tags: ,
Posted in flash experiments | Comments (0)

3Doodler – online 3D/2D sketch pad

April 3rd, 2010
by admin

3Doodler is… I will save my work and just ctrlv-ctrlc this paragraph from 3Doodler’s help:

3Doodler is one and half in one application. You can use it to generate 2D images ( simply by drawing them on canvas ) or to generate/texturize 3D models ( thus the number 3 in front of the application’s name ). 3Doodler took its name from merging of 2 expressions: “doodle” and “3D” which means the third dimension. So you can either doodle on 2D canvases or doodle on 3 dimensional models, or create new models by doodling on 2D canvas. In the end of this help, you will find some screencasts which explains how to complete certain tasks in 3Doodler, however these demos weren’t made by the real artist, so their artistic value is negligible.
After you finish your work, your doodles/sketches/models won’t go into the abyss of oblivion – by clicking “save”, you will store your sketch, and even replay of your work on server – this means that you can share your sketches with other people. When you create a new model, you won’t be able to save it on server – but you can save your work on your disk.

I’ve just quoted myself, so probably the quoting isn’t necessary, but… whatever.
To make this post more eye-catching, I will put some screenshots. From the logical point of view, they aren’t necessary, because you can just click this link and check everything out by yourself, but everything what concerns things like design,look and appearance isn’t too logical ( look at the appearance of some currently famous celebs, not too logical :) )

This is the 2D sketchpad ui ( ok, maybe not entire UI, I’ve cropped upper main menu and cut some grass on the bottom )
2D sketchpad uses different brushes: textured ones, photoshop-like ones, sprays.
The spray uses gaussian probability density function to make spray look more natural. Different sprays uses different blendModes.
There are also 3 special brushes I’ve “ripped off” ( he didn’t provide a source code, so I had several sleepless nights of working out how he did this ) of awesome Peter Blaskovic’s “Flame” – http://www.escapemotions.com/experiments/flame/#top . And I didn’t manage to obtain the same great effects that he had. But I don’t surrender my weapons and will try to get a bit closer to awesomeness of his flame ;)
EDIT: It appears that Peter Blaskovic didn’t invent these Flame-like shapes, this is an actual existing fractal structure by Scott Draves – http://en.wikipedia.org/wiki/Fractal_flame , I must include these thingies into 3Doodler

And now a few words about a 3D mode:

This is the texture editor:

This is a close-up to texture editor on real models:

And this is a screenshot of “custom model painter”, you paint your models and convert them to 3D. The screenshot is using the “Color” view mode, so the textures aren’t visible, but of course you  can change the view…

Now a little bit of gossip – 3Doodler allowed me to win polish FlexChallenge contest : ) yaay

Posted in flash experiments | Comments (1)

Flash movie ( swf ) launcher in AIR

March 26th, 2010
by admin

I wanted to make some kind of loader, which loads swf file, and accompanying asset files ( like for example dynamically loaded images or xml configuration files ) from one zip archive. Then we could have only 2 files – loader file and an archive with an application to load, instead of bunch of folders and files.
I wanted to make it cross-platform, so I’ve tried to do it in Adobe AIR ( standard flash player won’t allow us to create any files or folders ).
It would also serve as a Flex to AIR converter, becasue you add your Flex application’s files to data.zip archive, launch our AIR loader, and you have your Flex application running in AIR, without need to change xml files and so on.

We have AIR’s File class, which allows us to create folder and files.
So the basic idea is:

  • unpack data.zip into some temporary directory ( File.applicationStorageDirectory is recommended by Adobe lang reference… )
  • run some .swf file found in unpacked files.

Yes… No. That’s not possible. You cannot run files from appStorageDir. Stupid sandbox violation errors will appear. SandBox in standalone applications… gr8 idea.
You will think of a hack: Let’s load this swf into ByteArray, and then execute this ByteArray using Loader class!!!
for example:
var ldr:Loader = new Loader();
var fstream:FileStream = new FileStream();
fstream.open( YOUR_SWF_TO_LOAD , FileMode.READ );
ldr.load( fstream.readBytes() );

… Ok, it will run, but it won’t see any other files you’ve unpacked. Suppose we have config.xml in applicationStorageDirectory. It won’t see this config.xml, it will only see files in applicationDirectory – directory where our loader resides.
Ok: so let’s abandon this useless applicationStorageDirectory, and unpack everything to applicationDirectory. You think they will let you? Ha! You ingenuous little developer. They of course knows better what’s good for you. You can’t write to applicationDirectory. They say “it’s a bad practice”, and they also say “better use applicationStorageDirectory” They also say “make sandbox bridges to run active content from applicationStorageDirectory”. Sandbox bridges? This just some trivial feature in HTMLLoader class. SWF which runs in HTMLLoader is rendered by built-in flash AIR browser, and it runs 10x slower than it could in pure standalone flash player.
Ok, so we are still stuck with the problem – how to run this swf in AIR – and another problem – we can’t write to applicationDirectory. But wait… we can write to any other directory… So we can write to applicationDirectory too.
This is so stupid … Look, this causes security exception:
var new_directory:File = File.applicationDirectory.resolvePath( "some_new_directory" ); // create path to "some_new_directory" in our loader's directory
new_directory.createDirectory(); // <---- ERROR

And this doesn’t:
var new_directory:File = new File( File.applicationDirectory.resolvePath( "some_new_directory" ).nativePath );
new_directory.createDirectory();

We basically create new File object, with path equal to File.applicationDirectory/some_new_directory, but flash doesn’t know it’s our apps dir, so it doesn’t throw an exception. The rest is obvious – we execute .swf using File.applicationDirectory, because all files we need are actually in our application’s directory. And this is the simplest possible detour for these unnecessary sandbox “feature”.

And finally I’ve made this AIR swf loader, but… It appears, that files you load into AIR application has fewer fps, than they could have, when run stand-alone.
These are the mxml sources, along with some additional dependencies, in case you’d ever want to load some swf’s dynamically from AIR.
It depends on “newzip”, nochump’s zip loading library, which I’ve modified slightly, to support asynchrounous loading ( then if you’ll have 30MB zip, your flash won’t hang due to timeout exception ). Just build .air package along with your data.zip archive ( the .swf files to launch ) and you’re ready to go. Sample data.zip included.

sources

Tags: , , ,
Posted in flash experiments | Comments (0)

GenieFx genie OS-X effect update

March 15th, 2010
by admin

I had a few minutes to play with my old genie effect, so I’ve added two little features.
First one – the bounce effect. The genie seems to go too far, and then it comes back. It can be see when you open program windows ( not folder, but programs ) in OSX.
Second one – motion blur.
So there are two more parameters in the constructor, which tells GenieFx class , how far to bounce and how strong the motion blur will be:

new GenieFx(
( new demoBmp() ).bitmapData , /* object to animate - DisplayObject or BitmapData */
150 , /* x position of genie's "tail" */
0 , /* start from hidden image */
0.3 , /* bounce. 1.0 = bounce as high as the image height, 0.0 = nobounce */
8.0 /* vertical blur to simulate motion blur */

);

Sources: http://exp.teleranek.org/proj/genie/demo2.zip
Demo ( click the grey button-like object ):


ps. sorry for default WordPress’s CSS, it’s awful …
ps2… so the default WP theme was changed, the new one is much cooler :)

Tags: , ,
Posted in flash experiments | Comments (0)