Mar 20, 2009
3D Particle Emitter using Alchemy and FP10′s Drawing API
The demo I've posted is a modified port of the powerful Particle System API, a great tool used for OpenGL game development, using Alchemy. The API operates as a sequencer that performs actions on groups of particles. I managed to get 5,000 particles moving smoothly, but will boost that number significantly with some future optimization thanks to Ralph Hauwert.
The Alchemy side of port was a bit frustrating, mainly because of the lack of debugging tools. I had to fix weird bugs for things like parameter declarations on internal class constructors, but after a week of tinkering managed to get it running. I've heard there is an undocumented gdb client that comes with Alchemy, but haven't tried to figure it out. If anyone knows a good debugging technique, please let me know.
Using the new drawing API classes (Matrix3D, Utils3D, Vector3D) was a joy, if only for its simplicity and easy implementation. I wanted a quick way to display the data coming from C++, and it did the job well.
Speaking of speed, performance was absolutely not a concern for me with this port. My main objective was to port a powerful library for use in AS. I expected to see low frame rates, solely because of the straightforward marshaling technique I was using for the positions and color values. Both arrays are set through bytearrays marshaled through an emit method in C++. This seriously slows the player down when stepping through each bytearray to retrieve values. Even so, it does a good job of displaying 5,000 simultaneous particles.
Here is the main AS loop:
-
posData.position = 0;
-
colData.position = 0;
-
alcLib.emit(posData, colData);
-
posData.position = 0;
-
colData.position = 0;
-
-
rotX += (vmouse.y-rotX)*0.005;
-
rotY += (vmouse.x-rotY)*0.005;
-
-
if(trails.selected)
-
bitmapData.draw(clearData);
-
else
-
bitmapData.fillRect(bitmapData.rect, 0);
-
-
var loop:Number = posData.bytesAvailable/12;
-
for(var counter:int = 0; counter<loop; counter++) {
-
-
var x:Number;
-
var y:Number;
-
var z:Number;
-
-
x = posData.readFloat() * scale;
-
y = posData.readFloat() * scale;
-
z = posData.readFloat() * scale;
-
-
var r:Number;
-
var g:Number;
-
var b:Number;
-
var a:Number;
-
-
r = colData.readFloat()*255;
-
g = colData.readFloat()*255;
-
b = colData.readFloat()*255;
-
a = colData.readFloat()*255;
-
var argb:Number = (a <<24) | (r <<16) | (g <<8) | b;
-
-
var verts:Vector.<Number> = new Vector.<Number>();
-
var projectedVerts:Vector.<Number> = new Vector.<Number>();
-
var vertices:Vector.<Number> = new Vector.<Number>();
-
-
verts.push(x, y, z);
-
-
var matrix:Matrix3D =new Matrix3D();
-
matrix.appendRotation(rotY,Vector3D.Y_AXIS);
-
matrix.appendRotation(rotX,Vector3D.X_AXIS);
-
Utils3D.projectVectors(matrix,verts,vertices,new Vector.<Number>());
-
-
bitmapData.setPixel(vertices[0]+bitmapData.width*0.5, vertices[1]+bitmapData.height*0.5, argb);
-
}
Fixing the speed issue will involve applying Ralph Hauwert's Pixelbender projection method, which he managed to use to display 300,000+ simultaneous particles. I intend that to be the next phase in this project.
I'll be releasing the source as soon as I'm finished optimizing and attaching the proper callbacks. Stay tuned!
UPDATE: Performance has been optimized! Check out the latest post.




This is slick! Thanks for posting the example. And thanks a lot for the feedback on how we can make Alchemy better. If you have any other grips, feel free to drop me an email. The guy who did it is getting back from sabbatical soon, so I can fill up his mailbox
=Ryan
ryan@adobe.com
Thanks Ryan. I noticed some weird behavior with internal class constructors, but they were fairly minor. Parameters weren’t being set and I kept getting “terminate called without an active exception” errors. They were easy to fix, but a total pain to find because of the lack of debugging tools.
I find myself having the same problems with Alchemy. Although debugging is easier when you keep the generated .as, there’s no insight to the actual Alchemy bytecodes implemented. My workaround is to keep my main c++ class for alchemy seperated from a Mac based target. Just for compiling purposes, it makes debugging a bit easier.
That’s a good suggestion Ralph. I’ll try doing that.
cool! I’m getting about 35fps on old one and about 55fps on the new way. I guess they don’t call it Alchemy for nothing this stuff is gold.
I get about 21fps with my Macbook Pro on the optimized emitter, but I’ve seen it run 60fps on some i7′s in the office. I think I’ll do a 100,000 particle version just for benchmarking crazy machines.
[...] Particle Emitter using Alchemy and FP10’s Drawing API http://www.peternitsch.net/blog/?p=139 Optimizing the Alchemy Particle Emitter http://www.peternitsch.net/blog/?p=166 [...]