Adobe has recently released a preview version of Alchemy. From their site:
Welcome the preview release of codename “Alchemy.” Alchemy is a research project that allows users to compile C and C++ code that is targeted to run on the open source ActionScript Virtual Machine (AVM2). The purpose of this preview is to assess the level of community interest in reusing existing C and C++ libraries in Web applications that run on Adobe® Flash® Player and Adobe AIR®.
So, what does this mean? This means that we can use existing C/C++ code and compile that down to AS3. Initially I though that this implied a hefty increase in code execution speed, but as all is compiled down to AS3 this is not true in most cases. Code will only run faster if you ’stay’ on the C-side and only return to ‘AS3′ when your C code is done processing. The reason is that AS3 method-calls are sloooow (params need to be ‘unboxed’ etc.)! When in C this slowness doesn’t occur and hence execution speed will be faster (Adobe claims a potential speed increase by a factor 2 to 10 I beleive). Wow! That of course made me wonder whether Alchemy would be usefull for 3D engines like Papervision3D, more soon!
Branden Hall did a nice writeup on Alchemy explaining above better then me.
I couldn’t resist myself and started off immediately with something I always wanted to code for our 3D engine: Polygon Triangulation with support for holes.
I installed the Alchemy Toolkit, got the Flex 3.2 SDK and got some C code from the Department of Computer Science, UNC Chapel Hill.
Setting up the toolkit was bit tricky, but with help from this page I finally succeeded to get my environment right (OSX). Then I hit ‘make’ and presto! Got my swc! Download the swc and sample code or view a live example.
Some notes on swc usage:
1] ‘outer’ polygons must be defined anti-clockwise
2] ‘inner’ polygons (holes) must be defined clock-wise
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // import import cmodule.triangulation.CLibInit; // initialize var loader:CLibInit = new CLibInit; var lib:Object = loader.init(); // @vertices is an array of XY-pairs: [ [], [x0, y0], [x1, y1], ...] // NOTE: @vertices[0] should always be [] // @contours is an array containing the number of points of each polygon // => [4, 3, 3, 3] indicates 4 polygons with the first poly having 4 points, the second 3, etc. // @ncontours is the number of polygons (in our example: 4) // // @return An array of indices into the vertices array in form: [ [p0, p1, p2], [p0, p1, p2], ...] var indices : Array = lib.triangulate( vertices, contours, ncontours ); |
Here’s the relevant C code which was simply added to tri.c :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | static AS3_Val triangulate(void* self, AS3_Val args) { int ncontours = 0; int ccount; int npoints, first, last, n, nmonpoly; register int i; int op[SEGSIZE][3], ntriangles; AS3_Val dataVal; AS3_Val contourVal; AS3_Val retVal; AS3_Val temp; /* initialze the AS3 values */ dataVal = AS3_Undefined(); contourVal = AS3_Undefined(); retVal = AS3_Undefined(); temp = AS3_Undefined(); //parse the arguments. AS3_ArrayValue( args, "AS3ValType, AS3ValType, IntType", &dataVal, &contourVal, &ncontours ); //if no argument is specified if(dataVal == NULL || contourVal == NULL || ncontours <= 0) { AS3_Trace( AS3_String("Invalid input data!") ); return AS3_Null(); } ccount = 0; i = 1; while (ccount < ncontours) { int j; int k; //fscanf(infile, "%d", &npoints); npoints = AS3_IntValue( AS3_Get(contourVal, AS3_Int(ccount)) ); first = i; last = first + npoints - 1; for (j = 0, k = 1; j < npoints; j++, i++, k += 2) { //fscanf(infile, "%lf%lf", &seg[i].v0.x, &seg[i].v0.y); temp = AS3_Get(dataVal, AS3_Int(i) ); seg[i].v0.x = AS3_NumberValue( AS3_Get(temp, AS3_Int(0)) ); seg[i].v0.y = AS3_NumberValue( AS3_Get(temp, AS3_Int(1)) ); if (i == last) { seg[i].next = first; seg[i].prev = i-1; seg[i-1].v1 = seg[i].v0; } else if (i == first) { seg[i].next = i+1; seg[i].prev = last; seg[last].v1 = seg[i].v0; } else { seg[i].prev = i-1; seg[i].next = i+1; seg[i-1].v1 = seg[i].v0; } seg[i].is_inserted = FALSE; } ccount++; } n = i - 1; initialise(n); construct_trapezoids(n); nmonpoly = monotonate_trapezoids(n); ntriangles = triangulate_monotone_polygons(n, nmonpoly, op); retVal = AS3_Array("AS3ValType", NULL); for (i = 0; i < ntriangles; i++) { AS3_Val data = AS3_Array("IntType, IntType, IntType", op[i][0], op[i][1], op[i][2] ); AS3_Set(retVal, AS3_Int(i), data); } return retVal; } //entry point for code int main() { //define the methods exposed to ActionScript //typed as an ActionScript Function instance AS3_Val echoMethod = AS3_Function( NULL, echo ); AS3_Val triMethod = AS3_Function( NULL, triangulate ); // construct an object that holds references to the functions AS3_Val result = AS3_Object( "echo: AS3ValType", echoMethod ); AS3_SetS(result, "triangulate", triMethod); // Release AS3_Release( echoMethod ); AS3_Release( triMethod ); // notify that we initialized -- THIS DOES NOT RETURN! AS3_LibInit( result ); // should never get here! return 0; } |



November 27th, 2008 at 5:58 pm
Hello,
I am very interesting in focusing on this solution, but i can’t make your example work in the Flash IDE.
I downloaded the example files and created a .fla file which import the “TriangulationTest.as” main class as DocumentClass (and even on a Sprite from Library).
But nothing on screen…
I put a trace(”ok”) at the begining of the main function …. no trace !
After investigating, it seems that the following line
var loader : CLibInit = new CLibInit
(accessing the C compiled function) stops the player.
If I put comments after it and I got my trace…
What am i doing wrong ?
Can you explain me how to make it work in Flash IDE plz ?
Thanx.
November 27th, 2008 at 8:00 pm
Sorry, this is Flash 10 / CS4 only. Should have mentioned that in the post.
November 27th, 2008 at 8:36 pm
Ok, thanks for the article anyway
November 28th, 2008 at 4:28 am
adobe says 2 – 10 x *slower*, not faster as you wrote.
November 28th, 2008 at 7:27 pm
I quote Adobe:
“Alchemy is primarily intended to be used with C/C++ libraries that have few operating system dependencies. Ideally suited for computation-intensive use cases, such as audio/video transcoding, data manipulation, XML parsing, cryptographic functions or physics simulation, performance can be considerably faster than ActionScript 3.0 and anywhere from 2-10x slower than native C/C++ code. Alchemy is not intended for general development of SWF applications using C/C++.”
December 5th, 2008 at 8:09 pm
I dont know if you seen this, but http://makc.coverthesky.com/FlashFX/ffx.php?id=18
December 6th, 2008 at 12:18 am
That looks great makc! If I only knew before
December 12th, 2008 at 6:43 pm
Hello,
I got the Flash 10 Trial edition to try again, but i must have missed or forget something about SWC files…
Where am i supposed to put/include the swc file in flash 10 to get the example work ?
thanx
December 12th, 2008 at 6:49 pm
File => Publish Settings => Flash => Script Settings
Then add the swc there as ‘library path’ or ‘external library path’.
I hardly use CS4, so I’m not completely sure. But its a setting there for sure.
December 13th, 2008 at 10:10 am
Thank you very much
This is new stuff from Flash CS4 i didn’t know.
But i am facing a new problem when i compile, i got a error which is en open issue in the alchemy forum :
“ReferenceError: Error #1065: Variable MainTimeline is not defined”
The same problem exists on the EchoString example, so it seems that we have to compile under flex to make it work properly.
December 13th, 2008 at 7:46 pm
Ah, yes… Flex 3.2+ is required. Sorry about that, my bad.
December 16th, 2008 at 1:02 am
Finally thanks to Branden Hall, i successfully compiled your example with Flash CS4 by modifying 2 options from the publish settings :
1) as you said, File => Publish Settings => Flash => Script Settings, then add the swc there as ‘library path’ (”external library path causes an error)
2) check the “Export SWC” option
And that’s it
Hope this will help.
January 7th, 2009 at 11:11 pm
[...] huge excess of vertices and triangles and before I could figure out how to fix it, Tim Knip has posted this fantastic method in alchemy form that triangulates polys with holes without creating any extra [...]
March 12th, 2009 at 9:46 pm
I have been dealing with alchemy a bit here and there and I am trying to port the jpeg lib to use for compression of images. I am having issues including my files and being able to call any methods at all that the library is suppose to bring in. If there is any tips or recommendations you could give me, that’d be awesome! thank you