<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>zero point nine &#187; flash</title>
	<atom:link href="http://www.zeropointnine.com/blog/category/flash/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.zeropointnine.com/blog</link>
	<description>lee felarca - personal work and findings</description>
	<lastBuildDate>Fri, 04 Nov 2011 13:19:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>FPO Image Generator</title>
		<link>http://www.zeropointnine.com/blog/fpo-image-generator/</link>
		<comments>http://www.zeropointnine.com/blog/fpo-image-generator/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 15:07:31 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[sourcecode]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=1018</guid>
		<description><![CDATA[Is it not the norm for the agency developer of whatever flavor to be asked make more progress than what&#8217;s reasonable based on the current status of a given project at any given point in time? Thus, we continuously look for ways to make more progress with less information, even while increasing the risk of [...]]]></description>
			<content:encoded><![CDATA[<div class="paragraph1">
<div class="imageright"><a href="/blog/assets/FpoImageGenerator_screenshot.jpg" target="_blank"><img border="0" src="/blog/assets/FpoImageGenerator_thumb.jpg" alt="Thumbnail" /></a></div>
<p>Is it not the norm for the agency developer of whatever flavor to be asked make more progress than what&#8217;s reasonable based on the current status of a given project at any given point in time?</p>
<p>Thus, we continuously look for ways to make more progress with less information, even while increasing the risk of wasted work and unseemly displays of developer angst. At the very least, such experiences make a person receptive to finding a few tricks that might shave off a few extra minutes in one&#8217;s pursuit to meet the latest unreasonable deadline. </p>
<p>That having been said, the potential utility of this little tool should require no further explanation.</p>
<p>It has its origins in this capricious <a href="http://twitter.com/#!/zeropointnine/status/27805279504568320" target="_blank">tweet</a> from some time last winter.</p>
<p>- <a href="/blog/assets/FpoImageGenerator_20111103.air"><strong>Download</strong></a> (uses Adobe AIR)</p>
<p>- <a href="/blog/assets_code/FpoImageGenerator_source_09.zip"><strong>Source</strong></a> (Flex project)
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/fpo-image-generator/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Updated FLV Encoder, 3.5x faster with Alchemy</title>
		<link>http://www.zeropointnine.com/blog/updated-flv-encoder-alchem/</link>
		<comments>http://www.zeropointnine.com/blog/updated-flv-encoder-alchem/#comments</comments>
		<pubDate>Wed, 30 Mar 2011 14:32:45 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[sourcecode]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=898</guid>
		<description><![CDATA[Demo: Record and encode FLV&#8217;s from webcam in realtime, using AlchemyOr, download AIR desktop version This is an update to FLV Encoder which adds an optional Alchemy routine that&#8217;s about 3.5x faster, as well as FileStream support for writing directly to a local file using AIR. The library has been architected in such a way [...]]]></description>
			<content:encoded><![CDATA[<div class="vimeoBox" style="padding-left:20px; padding-bottom:10px; width:200px;"><img src="/blog/assets/WebcamRealTimeFlvEncoder_thumb.jpg" onclick="javascript:showBox('WebcamRealTimeFlvEncoder',340,440,'e5e5e5',this);" alt="Thumbnail - Click me" style="cursor: pointer" />
<div style="padding-top:12px;"><em>Demo: Record and encode FLV&#8217;s from webcam in realtime, using Alchemy<br/><br/>Or, <a href="/blog/assets/WebcamRealtimeFlvEncoder.air">download AIR desktop version</a></em></div>
</div>
<p>This is an update to FLV Encoder which adds an optional Alchemy routine that&#8217;s about 3.5x faster, as well as FileStream support for writing directly to a local file using AIR. The library has been architected in such a way that you can use the package while targeting either the browser (no FileStream support) or AIR, and either Flash 9 (no Alchemy support) or Flash 10 &#8211; without getting class dependency compiler errors. </p>
<p>I&#8217;ve put the package on <a href="https://github.com/zeropointnine/leelib" target="_blank">Github</a>, along with a couple examples (including the one from the <a href="http://www.zeropointnine.com/blog/flv-encoder-with-audio/">last post</a>). The API has changed a little so be sure to also see the example code below. A method <code>updateDurationMetadata()</code> has been added so the video duration does not have to be declared before the video has been created. Also, a bug where the top-most line of pixels was not being written has been fixed.</p>
<p><strong>Realtime encoding demo:</strong></p>
<p>Because of the increased speed of the Alchemy version, it is now viable to encode FLV&#8217;s in realtime as the audio and video is being captured, at least within certain limits. Click on the thumbnail above for an online demo that encodes webcam video and audio to a file at 320&#215;240 in real time. If your system is fast enough, you can keep the framerate set to 15FPS with minimal hiccups. The browser-based version must store the entire FLV in memory before saving to disk, but the <a href="/blog/assets/WebcamRealtimeFlvEncoder.air">equivalent AIR version</a> can save its contents directly to a file so that the only limiting factor is disk space. I&#8217;m using a dynamic timing and queuing system to keep video and audio in sync which could be the topic of another post.</p>
<p><strong>Updated usage examples:</strong></p>
<p><span id="more-898"></span></p>
<p>[A] To encode an FLV to a ByteArray, start by instantiating <code>ByteArrayFlvEncoder</code>. The rest is similar to the last version, but you can now call <code>updateDurationMetadata()</code> when you&#8217;re done to update the duration property in the metadata. Finally, call <code>kill()</code> to prepare the object for garbage collection:</p>
<p>[as3]<br />
var baFlvEncoder:ByteArrayFlvEncoder = new ByteArrayFlvEncoder(myFrameRate);</p>
<p>baFlvEncoder.setVideoProperties(myWidth, myHeight, VideoPayloadMakerAlchemy);<br />
// (Omit the 3rd argument to NOT use Alchemy if you&#8217;re targeting Flash 9)<br />
baFlvEncoder.setAudioProperties(BaseFlvEncoder.SAMPLERATE_44KHZ, true, false, true);</p>
<p>baFlvEncoder.start();</p>
<p>baFlvEncoder.addFrame(myBitmapData, myAudioByteArray);<br />
baFlvEncoder.addFrame(myBitmapData, myAudioByteArray); // etc.</p>
<p>baFlvEncoder.updateDurationMetadata();</p>
<p>saveOutMyFileUsingFileReference( baFlvEncoder.byteArray );</p>
<p>baFlvEncoder.kill(); // for garbage collection<br />
[/as3]</p>
<p>[B] To encode an FLV directly to a local file (in AIR), instantiate <code>FileStreamFlvEncoder</code> with a <code>File</code> reference, and open up the exposed <code>FileStream</code>, and then close it when you&#8217;re all done:</p>
<p>[as3]<br />
var myFile:File = File.documentsDirectory.resolvePath(&#8220;video.flv&#8221;);<br />
var fsFlvEncoder:FileStreamFlvEncoder = new FileStreamFlvEncoder(myFile, myFrameRate);<br />
fsFlvEncoder.fileStream.openAsync(myFile, FileMode.UPDATE);</p>
<p>fsFlvEncoder.setVideoProperties(myWidth, myHeight, VideoPayloadMakerAlchemy);<br />
fsFlvEncoder.setAudioProperties(BaseFlvEncoder.SAMPLERATE_44KHZ, true, false, true);</p>
<p>fsFlvEncoder.start();</p>
<p>fsFlvEncoder.addFrame(myBitmapData, myAudioByteArray);<br />
fsFlvEncoder.addFrame(myBitmapData, myAudioByteArray); // etc.</p>
<p>fsFlvEncoder.updateDurationMetadata();</p>
<p>fsFlvEncoder.fileStream.close();</p>
<p>fsFlvEncoder.kill();<br />
[/as3]</p>
<p>A new instance of FlvEncoder should be created for every new FLV to be generated. </p>
<p>If you&#8217;re using the Alchemy version, the SWC lives in <code>leelib/util/flvEncoder/alchemy</code>, so be sure add that folder to your project library path. The C++ code is there as well.</p>
<p>Note that the current Alchemy video encoding routine is being done synchronously, which means that although it&#8217;s much faster than the regular AS3 version, the main Flash thread must still wait for the Alchemy encoding to be done before continuing. An asynchronous version would allow for a real-time encoding scenario that is more flexible and probably with less &#8216;dropouts&#8217;, and would probably prompt the need an internal queuing system. Anyway, this warrants further development.</p>
<p><strong>- <a href="https://github.com/zeropointnine/leelib" target="_blank">Source code</a></strong> (Github)</p>
<p class="creacom">Licensed under a <a href="http://creativecommons.org/licenses/by/3.0/" rel="license" target="_blank">Creative Commons Attribution 3.0 License</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/updated-flv-encoder-alchem/feed/</wfw:commentRss>
		<slash:comments>46</slash:comments>
		</item>
		<item>
		<title>FLV Encoder with Audio</title>
		<link>http://www.zeropointnine.com/blog/flv-encoder-with-audio/</link>
		<comments>http://www.zeropointnine.com/blog/flv-encoder-with-audio/#comments</comments>
		<pubDate>Sun, 13 Mar 2011 03:51:54 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[flash]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=848</guid>
		<description><![CDATA[FlvEncoder demo implementation: Records webcam video and audio to a local file ! Update: See updated FLV Encoder post + code here A prospective client recently approached me about the possibility of adding audio support to SimpleFlvEncoder. They ultimately decided to go a different direction and so didn&#8217;t commission me for that work, but not [...]]]></description>
			<content:encoded><![CDATA[<div class="vimeoBox" style="padding-left:20px; padding-bottom:20px; width:200px;"><img src="/blog/assets/FlvEncoderRedux_thumb.jpg" onclick="javascript:showBox('FlvEncoderRedux',340,290,'e5e5e5',this);" alt="Thumbnail - Click me" style="cursor: pointer" />
<div><em>FlvEncoder demo implementation: Records webcam video and audio to a local file</em></div>
</div>
<p><span style="font-style:italic;"><a href="http://www.zeropointnine.com/blog/updated-flv-encoder-alchem/">! Update: See updated FLV Encoder post + code here</a></span></p>
<p>A prospective client recently approached me about the possibility of adding audio support to <a href="">SimpleFlvEncoder</a>. They ultimately decided to go a different direction and so didn&#8217;t commission me for that work, but not before my curiosity had already gotten the better of me&#8230; </p>
<p>This class makes it possible to create FLV&#8217;s in AS3 that contain both video and audio, all on the client-side using the regular browser-based Flash Player. Like with the old version from 2007 (!), video is uncompressed (or rather, just zlib-compressed on a per-frame basis). Audio must be supplied in uncompressed PCM format with either 8 or 16 bits per sample, mono or stereo, and at 11, 22, or 44 KHz. It can also create FLV&#8217;s that contain only audio or only video.</p>
<p>Here is a quick-and-hand-wavey example of using the class (Please see the comments in the source for more detail.).<span id="more-848"></span></p>
<pre><code>
var flvEncoder:FlvEncoder = new FlvEncoder(_fps, _duration);
flvEncoder.setVideoProperties(_videoWidth, _videoHeight);
flvEncoder.setAudioProperties(FlvEncoder.SAMPLERATE_44KHZ, _is16Bit, _isStereo);
flvEncoder.begin();

for (var i:int = 0; i < _numFrames; i++)
{
	flvEncoder.addFrame(_myBitmaps[i], _myChunksOfAudio[i]);
}

saveOutMyFile( flvEncoder.byteArray );

</code></pre>
<p>The old "SimpleFlvEncoder" class, which dealt only with video, was stupidly simple to use. Having to deal with audio ends up being a little more involved. As I said, you have to supply the audio data in PCM format, which basically just means raw, uncompressed audio. You give it the audio data in the <code><b>addFrame()</b></code> method. You might gather that data using <code>Sound.extract()</code> or <code>SampleDataEvent</code>, or by dynamically generating your own. Use <code><b>audioFrameSize</b></code> to determine how much audio data in bytes is expected per frame. </p>
<p>Supplying too little or too much audio per frame is I believe "legal" per the FLV spec, so the class will take whatever size ByteArray is given to it for audio. An incorrect amount may result either in an unexpected framerate on playback or choppiness in the audio depending on the FLV playback implementation of the client program.</p>
<p>It's beyond the scope of this post to provide a tutorial-like explanation of playing with audio data in Flash, but let me describe what I think are the three most likely use-cases for this class when it comes to audio. </p>
<p>One is where the audio is static (e.g., a soundtrack that accompanies the video). In this case, you could load/embed an uncompressed WAV file into a ByteArray and basically just feed the correct number of bytes from that ByteArray to the addFrame() method without much drama (Uncompressed WAV files are just raw PCM audio data with some metadata at the beginning; you would start copying the bytes from after the end of the <a href="https://ccrma.stanford.edu/courses/422/projects/WaveFormat/" target="_blank">metadata</a>). Alternatively, you could use <code>Sound.extract()</code> on an MP3, etc.</p>
<p>Another is where the audio comes from the webcam, which is what I'm doing in the sample implementation above. I'm using a modified version of Thibault Imbert's <a href="http://www.bytearray.org/?p=1858">MicRecorder</a> class to collect the audio data into one big audio ByteArray and then chunking out the pieces of it to FlvEncoder in a loop at the very end, which basically amounts to the same thing as the first scenario.</p>
<p>The last is where the audio is dynamic, presumably accompanying video which is equally dynamic, like for a game or other interactive experience. Unfortunately, it's impossible to record the global sound output from Flash using <code>SampleDataEvent</code> or anything else (though I'd be happy to be proven wrong). Just for the hell of it I tried using <code>SoundMixer.computeSpectrum()</code> on a really quick interval for the task, and was able to get something approximating what was needed, but it was predictably... way not good enough. Anyway, this means you would need to create something like a sound mixing engine, or possibly use some extant AS3 sound compositing library. </p>
<p>The last thing to say on this for the time being is that I tried my hand at Alchemy for the first time and made a version of the encoder that runs about 3x faster, but as a C++ and Alchemy noob, couldn't get rid of a memory leak and then gave up on it for the time being. If you're well versed at this sort of thing please let me know and I will happily send you the code. Otherwise, I will hopefully return to it at some point and post an update.</p>
<p>If the encoder is quick enough and the CPU demands of the dynamically generated video content are low enough, the FLV could be created in real time as the content is being produced, rather than storing all the bitmaps and audio data in memory and doing it all at the end; this might be viable under some limited use cases (i.e., low enough CPU use by Flash + low enough frame rate + small enough video size + fast enough computer).</p>
<p>Last last thing: I've always thought one of the coolest open source AS3 projects would be to use Alchemy with the <a href="http://www.xvid.org" target="_blank">Xvid</a> or <a href="http://www.videolan.org/developers/x264.html" target="_blank">x264</a> C library to do client-side all-Flash Xvid or h264 video encoding (An "easier" solution would be AIR w/ NativeProcess + ffmpeg, but that kind of ruins the fun.). Anyway, just putting it out there...</p>
<p>-  <a href="/blog/assets_code/FlvEncoder_v0.9" style="text-decoration:line-through;"">Source code for FlvEncoder</a><br />
- <strong><a href="http://github.com/zeropointnine/leelib/tree/master/src">Updated version on Github</a></strong></p>
<p class="creacom">Licensed under a <a href="http://creativecommons.org/licenses/by/3.0/" rel="license" target="_blank">Creative Commons Attribution 3.0 License</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/flv-encoder-with-audio/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>3D Character Configurator (maqet.com)</title>
		<link>http://www.zeropointnine.com/blog/3d-character-configurator-maqet-com/</link>
		<comments>http://www.zeropointnine.com/blog/3d-character-configurator-maqet-com/#comments</comments>
		<pubDate>Thu, 03 Feb 2011 19:20:31 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[flash]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=765</guid>
		<description><![CDATA[Easily the most interesting and innovative commercial project I&#8217;ve been involved with over the last period of time has been maqet.com, which is created and run by artist Keith Cottingham. I&#8217;ve been responsible for the site&#8217;s configurator component, which allows the user to create customized maquettes by changing their poses and skin. The &#8220;maqet&#8221; is [...]]]></description>
			<content:encoded><![CDATA[<p>Easily the most interesting and innovative commercial project I&#8217;ve been involved with over the last period of time has been <a href="http://www.maqet.com" target="_blank">maqet.com</a>, which is created and run by artist <a href="http://www.kcott.com" target="_blank">Keith Cottingham</a>. </p>
<p>I&#8217;ve been responsible for the site&#8217;s configurator component, which allows the user to create customized maquettes by changing their poses and skin. The &#8220;maqet&#8221; is then created in physical form through a 3D-printing process and delivered to the user. </p>
<p>Most recently, I&#8217;ve been working on the drawing tools that allow the user to paint on a two-dimensional canvas that updates the texture of the 3D model in real-time. Soon to be added is a freehand drawing-to-bezier curve tool.  </p>
<iframe src='http://player.vimeo.com/video/19503190?title=1&amp;byline=1&amp;portrait=1' width='560' height='336' frameborder='0'></iframe>
<p>This is a quick-and-dirty video capture of the configurator in action. But mostly, please feel encouraged to <a href="http://www.maqet.com" target="blank">visit the site</a> and try it for yourself.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/3d-character-configurator-maqet-com/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using NativeProcess in AIR 2 for screencaps</title>
		<link>http://www.zeropointnine.com/blog/using-nativeprocess-in-air-2-for-screencaps/</link>
		<comments>http://www.zeropointnine.com/blog/using-nativeprocess-in-air-2-for-screencaps/#comments</comments>
		<pubDate>Mon, 19 Apr 2010 02:15:45 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[dot net]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[sourcecode]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=498</guid>
		<description><![CDATA[Download installable AIR fileRequires AIR 2 Beta 2 Runtime +Windows .NET v3.5 My aim here was to get familiar with AIR 2&#8242;s new capability of interacting with external processes&#8217; standard streams. One useful way of learning how to use a new feature is to proceed directly to trying to abuse it. To that end, this [...]]]></description>
			<content:encoded><![CDATA[<div class="paragraph1">
<div class="imageright"><a href="/blog/assets/NativeProcessTest_Installer.zip"><img border="0" src="/blog/assets/NativeProcessTest_t.jpg" alt="Thumbnail" /><br/><br/><strong>Download installable AIR file</a></strong><br/><em style="font-size:10px">Requires AIR 2 Beta 2 Runtime +<br/>Windows .NET v3.5</em></div>
<p>My aim here was to get familiar with AIR 2&#8242;s new capability of interacting with external processes&#8217; standard streams.</p></div>
<p>One useful way of learning how to use a new feature is to proceed directly to trying to abuse it. </p>
<p>To that end, this AIR application takes in a fairly continuous stream of uncompressed binary image data from a native process&#8217; standard output. My hope was to get real-time screen capture updates into AIR at a decent frame rate.</p>
<p>Details and source code after the break&#8211;</p>
<p><span id="more-498"></span></p>
<p><strong>The native process</strong></p>
<p>For my &#8220;native process,&#8221; I created a Windows .NET application written in C#. When asked, it takes a screen capture of the desktop and sends the image data through the process&#8217; standard output. For various reasons, I chose to set it up as a Windows form rather than as a plain vanilla console or as a real system service. The <a href="/blog/assets_code/NativeProcessTest_Form1.cs.txt" target="_blank">relevant C# code</a> is only a few dozen lines long. One interesting function there is <code>bitmapToBytes()</code>, which converts a bitmap into a byte array in the correct format for Flash to be able to apply it directly to a BitmapData without any further (costly) conversion. </p>
<p><strong>The AIR application</strong></p>
<p>On the &#8220;client-side,&#8221; the Flash AIR application has little to do. It simply sends a command to the native process, telling it to take a screen grab, along with image dimension and offset parameters. Because the client takes in the resulting stream of data in packets whose length should not be assumed to be of any given size, it needs to know where in the data a new image starts and where it ends. So it checks the stream for an arbitrary 4-byte start code as well as a termination code. When the transfer is complete, it just applies the resulting data, collected over time into a ByteArray, using <code>BitmapData.setPixels()</code>. It then requests a new image, and so on.</p>
<p><strong>Performance considerations</strong></p>
<p>On a mid-range quad-core PC using 1280&#215;1024 images (5MB per uncompressed frame), I&#8217;m getting about 8 frames per second, or 125ms per frame. The time it takes for the 5MB image to transfer through the standard stream is about 65ms, or 50% of the total time for one iteration; without setting up an honest benchmark test, it&#8217;d be unfair and/or impolitic to declare that AIR represents a bottleneck here, so &#8230; yeah.</p>
<p>The AIR app eats up about 2/3 of one CPU core using the runtime&#8217;s main application thread. The remaining 1/3 represents the amount of time the AIR app has to wait while the native process constructs the screengrab. If the app were re-architected in such a way that the native process always has a new screencap queued up and ready to send &#8211; leading to little or no idle time between request and response &#8211; the AIR app would easily soak a full CPU core. Since the AIR app is doing little of significance besides reading the process&#8217;s standard stream and collecting that info into a byte array, it appears that merely handling large amounts of stdout data is quite costly. </p>
<p>Of course, AIR 2 isn&#8217;t even final yet. Nevertheless, I thought these preliminary findings were interesting. (This build targets Beta 2, which is the most recent public beta of AIR 2; compiling and running it against the most recent non-public beta of the SDK and runtime dated April 9, 2010 gave the same results.)</p>
<p><strong>Source files</strong></p>
<p>Setting up a native process for use with AIR 2 is well documented so I didn&#8217;t bother commenting on that here. However, the included source is I believe a good starting point for adapting to whatever native process craziness you may be cooking up&#8230; </p>
<div style="margin-left:35px; padding-top:10px; padding-bottom:10px;">
<a href="/blog/assets/NativeProcessTest_Installer.zip"><strong>AIR application</strong></a> (requires <a href="http://labs.adobe.com/downloads/air2.html" target="_blank">AIR 2 Beta 2 runtime</a> and <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=333325fd-ae52-4e35-b531-508d977d32a6&#038;displaylang=en" target="_blank">.NET v3.5 for Windows</a>)<br />
<a href="/blog/assets_code/NativeProcessTest.as.txt" target="_blank"><strong>Main AS3 class file</strong></a><br />
<a href="/blog/assets_code/NativeProcessTest_Form1.cs.txt" target="_blank"><strong>Main C# class file </strong></a><br />
<a href="/blog/assets_code/NativeProcessTest_projectfiles.zip"><strong>Full project source</strong></a> (Flash Builder 4 + Visual Studio 2008)
</div>
<p>For another implementation of AIR 2 screen capture, see <a href="http://corlan.org/2009/11/30/magnifying-glass-air-2-application-or-how-to-communicate-with-a-java-program-from-air/" target="_blank">this post by Mihai Corlan</a>, also with source, using Java. There are also a few other related examples out there as well.</p>
<p class="creacom">Licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/" target="_blank">Creative Commons Attribution 3.0 License</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/using-nativeprocess-in-air-2-for-screencaps/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>More Fun With Texture Projection</title>
		<link>http://www.zeropointnine.com/blog/more-fun-with-texture-projection/</link>
		<comments>http://www.zeropointnine.com/blog/more-fun-with-texture-projection/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 22:09:51 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[augmented reality]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[flash 3d]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=462</guid>
		<description><![CDATA[Here I&#8217;m just expanding upon the &#8216;texture extraction&#8217; idea posted before. This version maps video onto 3D objects in a much more direct manner by using ray-casting, like the examples in the last several posts. Controls: Mouse rotates object Mouse drag moves object [SPACE] remaps the texturing of the 3d object [ENTER] cycles through different [...]]]></description>
			<content:encoded><![CDATA[<div class="paragraph1">
<div class="imageright"><img style="cursor: pointer" onclick="javascript:showBox('TextureExtractarFun',800,600, '444444',this);" src="/blog/assets/TextureExtractarFun_t.jpg" alt="Thumbnail - Click me" /></div>
<p>Here I&#8217;m just expanding upon the &#8216;texture extraction&#8217; idea posted <a href="/blog/augmented-reality-texture-extraction-experiment/">before</a>. This version maps video onto 3D objects in a much more direct manner by using ray-casting, like the examples in the last several posts. </div>
<p><em>Controls:</em></p>
<ul style='margin-left:15px;'>
<li>Mouse rotates object</li>
<li>Mouse drag moves object</li>
<li>[SPACE] remaps the texturing of the 3d object</li>
<li>[ENTER] cycles through different 3D primitives</li>
<li>[H] shows full list of kludgey hotkey controls</li>
</ul>
<p><em>Update with video (8/25/2010)</em>:</p>
<div style="text-align:center; padding-top:11px; padding-bottom:5px;"><iframe src='http://player.vimeo.com/video/14401231?title=1&amp;byline=1&amp;portrait=1' width='560' height='420' frameborder='0'></iframe></div>
<p>Although this piece dispenses with the encumbrances of an AR marker or any application-like functionality, I think the method being used here has some potentially interesting uses for an augmented reality-based design application. (Or for more whimsical uses like &#8220;upload-your-face&#8221; done in 3D). I&#8217;ve disabled backface detection, so the imagery gets mapped on all sides of the object rather than just the camera-facing polys, which makes it more visually interesting. Live demo above requires webcam. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/more-fun-with-texture-projection/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Augmented Reality Texture Extraction Experiment</title>
		<link>http://www.zeropointnine.com/blog/augmented-reality-texture-extraction-experiment/</link>
		<comments>http://www.zeropointnine.com/blog/augmented-reality-texture-extraction-experiment/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 00:57:11 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[augmented reality]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[flash 3d]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=400</guid>
		<description><![CDATA[This is an AR-based experiment that enables the user to lift textures from real-world objects in live video and apply them onto 3D objects that are overlayed on top of them. Only box primitives are supported here, but the general idea could be extended to other types of 3D primitives or potentially even more complex [...]]]></description>
			<content:encoded><![CDATA[<p>This is an AR-based experiment that enables the user to lift textures from real-world objects in live video and apply them onto 3D objects that are overlayed on top of them. Only box primitives are supported here, but the general idea could be extended to other types of 3D primitives or potentially even more complex objects with some clever image compositing and UV mapping. </p>
<div style="text-align:right; padding-top:11px; padding-bottom:5px;"><iframe src='http://player.vimeo.com/video/6660264?title=1&amp;byline=1&amp;portrait=1' width='560' height='420' frameborder='0'></iframe></div>
<div class="paragraph1">
<div class="imageright" style="text-align:right; font-size:10px;"><img style="cursor: pointer" onclick="javascript:showBox('TextureExtractAR',800,600, '444444',this);" src="/blog/assets/TextureExtractAR_t.jpg" alt="Thumbnail - Click me" /><br/>Click for live demo</div>
<p>Click the image on the right to run a live version of the experiment, in case you have the patience to suffer thru the quick-and-dirty hotkey-based UI. </p>
<p><strong>Print the AR marker</strong> (<a href="/blog/assets/TextureExtractAR_marker.pdf" target="_blank">PDF</a> | <a href="/blog/assets/TextureExtractAR_marker.png" target="_blank">PNG</a>) and point your webcam at it. </p>
<p>It&#8217;s running Saqoosha&#8217;s (feature-incomplete) <a href="http://www.libspark.org/log/as3/FLARToolKit/branches/alchemy" target="_blank">Alchemy branch</a> of the FLAR Toolkit, along with Papervision3D.
</div>
<div style="clear:right;"/>
<p>In the future, it would be nice to figure out is how to apply bilinear filtering to the &#8216;deperspectivized&#8217; textures. I could also add a feature to export the textured 3d objects into a 3D file format (probably OBJ) if there&#8217;s any interest. </p>
<p>Conceptually, this piece builds on <a href="/blog/video-projector-effect-advanced/">these</a> <a href="/blog/video-projector-effect/">two</a> video projection tests, and is a modest implementation of one of the themes from <a href="/blog/a-few-ideas-for-augmented-reality/">this post</a> of ideas for augmented reality.
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/augmented-reality-texture-extraction-experiment/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Complex Spotlight Shadow Caster for Papervision3D</title>
		<link>http://www.zeropointnine.com/blog/complex-spotlight-shadow-caster-in-papervision3d/</link>
		<comments>http://www.zeropointnine.com/blog/complex-spotlight-shadow-caster-in-papervision3d/#comments</comments>
		<pubDate>Tue, 09 Jun 2009 03:01:32 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[flash]]></category>
		<category><![CDATA[flash 3d]]></category>
		<category><![CDATA[sourcecode]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=366</guid>
		<description><![CDATA[Simulates the projection of shadows coming from a spotlight light source onto irregular surfaces. In the supplied example, an animated MD2 model (from Quake 2) is casting a shadow onto the inside of a sphere. Supported parameters include shadow color, alpha, blur, falloff and texture map size, as well as position, rotation and field of [...]]]></description>
			<content:encoded><![CDATA[<div class="paragraph1">
<div class="imageright"><img style="cursor: pointer" onclick="javascript:showBox('shadowcaster',780,780, '444444',this);" src="/blog/assets/shadowcaster_t.jpg" alt="Thumbnail - Click me" /></div>
<p>Simulates the projection of shadows coming from a spotlight light source onto irregular surfaces. In the supplied example, an animated MD2 model (from Quake 2) is casting a shadow onto the inside of a sphere. Supported parameters include shadow color, alpha, blur, falloff and texture map size, as well as position, rotation and field of view. This evolves out of the projection work posted previously.</p></div>
<p><strong>Source:</strong></p>
<p><a href="/blog/assets_code/SpotlightShadowCasterManager.as.txt" target="_blank">SpotlightShadowCasterManager.as</a></p>
<p><strong>Usage:</strong></p>
<p>After instantiating the manager &#8211;</p>
<pre>	_shadowCaster = new SpotlightShadowCasterManager();</pre>
<p>&#8211; assign one or more DisplayObject3D&#8217;s that will block the light from the spotlight:</p>
<pre>	_shadowCaster.registerShadowCasterObject(myMesh);</pre>
<p>Then register one or more meshes that can have shadows cast upon it with <code>registerShadowCasterObject</code>. As the second argument, you must supply a <code>BitmapMaterial</code> utilized by the mesh on which the manager will draw the shadows. Usually, you&#8217;ll want to create a <code>CompositeMaterial</code>, with the <code>BitmapMaterial</code> most likely at the top of the stack. It might look something like this:</p>
<pre>	var compositeMaterial = new CompositeMaterial();
	compositeMaterial.addMaterial( new ColorMaterial(0x888888) );
	var mat:BitmapMaterial = new BitmapMaterial( new BitmapData(1,1) );
	// .. the bitmapdata will get overwritten,
	//    but must contain _something_
	var sphere:TriangleMesh3D = new Sphere(compositeMaterial, 1000);

	_shadowCaster.registerShadowReceiverObject(sphere, mat);</pre>
<p>To update the shadow textures, call</p>
<pre>	_shadowCaster.update();</pre>
<p>&#8211; probably in your <code>onEnterFrame</code> or <code>onRenderTick</code> function.</p>
<p>That&#8217;s enough to get going. From there, it&#8217;s just a matter of adjusting the projector&#8217;s position and orientation in relation to the objects in your scene with the properties <code>projectorPosition</code>, <code>projectorPitch</code>, and <code>projectorRoll</code>. Check the source for the various configurable properties like blur, alpha, color, etc.</p>
<p><strong>Limitations, bugs:</strong></p>
<p><span id="more-366"></span>- As described above, objects must be manually assigned to be either a &#8216;caster&#8217; or a &#8216;receiver&#8217;. These roles aren&#8217;t determined dynamically by the class itself.</p>
<p>- Only one level of shadows is supported. Adding an arbitrary number wouldn&#8217;t be difficult, just cumbersome to manage under the current system, and increasingly expensive.</p>
<p>- Unfortunately, a &#8216;shadow receiver&#8217; object can&#8217;t have its own texture in addition to the one used to cast shadows onto, at least not in a way that looks decent. The reason is that a 3d object in Papervision3D has only one set of UV texture data and the shadow texture overwrites this with every update.</p>
<p>- There&#8217;s undoubtedly a less expensive way to do the raycasting/projection in the main math routine in the private function <code>updateMesh</code>. If you&#8217;re adept at this kind of thing, please send your improvements!</p>
<p>- Ugly and obvious artifacts show up on the &#8216;projectable&#8217; textures when the spotlight is rotated 90 degrees away them. (You may have already noticed this in the previous two projection experiment posts).  Again, I&#8217;d love any solutions anyone has for this.</p>
<p class="creacom">Licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/" target="_blank">Creative Commons Attribution 3.0 License</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/complex-spotlight-shadow-caster-in-papervision3d/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Video Projector Effect, Advanced</title>
		<link>http://www.zeropointnine.com/blog/video-projector-effect-advanced/</link>
		<comments>http://www.zeropointnine.com/blog/video-projector-effect-advanced/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 03:15:22 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[flash]]></category>
		<category><![CDATA[flash 3d]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=335</guid>
		<description><![CDATA[This version handles arbitrary rotations, field of view / focal length, and uses correct math; the previous example faked it somewhat, doing everything basically with 2D math (but why admit to that? :). I found it twice as difficult getting to this point compared to the version posted a few days ago. It turns out [...]]]></description>
			<content:encoded><![CDATA[<div class="paragraph1">
<div class="imageright"><img src="/blog/assets/ProjectorEffectAdv_t.jpg" onclick="javascript:showBox('ProjectorEffectAdv',780,780, '444444',this);" alt="Thumbnail - Click me" style="cursor: pointer" /></div>
<p>This version handles arbitrary rotations, field of view / focal length, and uses correct math; the <a href="/blog/video-projector-effect">previous example</a> faked it somewhat, doing everything basically with 2D math (but why admit to that? :). I found it twice as difficult getting to this point compared to the version posted a few days ago. It turns out that when you want to rotate more than 90 degrees around the x-axis, it&#8217;s good to make friends with quaternions, if only superficially.</p>
<p>And it&#8217;s interactive this time. By the way, is it not a royal pain to design an interface to control more than two axes in Flash for the web?</p>
<p>There&#8217;s still a lot that could be done right / better with this: backface culling (already tried and failed); frustrum culling; per-triangle alpha based on distance and angle to simulate light intensity; per-triangle focus/blur based on distance, maybe (but probably not); a more straightforward way to implement video; shadows&#8230; Basically, anything short of building a renderer-inside-a-renderer.</p>
<p>Bonus points for identifying the band to whom the set list pictured in the third image belongs.</p>
<p>Sorry, still no source.<br />
<br/>&nbsp;
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/video-projector-effect-advanced/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Video Projector Effect</title>
		<link>http://www.zeropointnine.com/blog/video-projector-effect/</link>
		<comments>http://www.zeropointnine.com/blog/video-projector-effect/#comments</comments>
		<pubDate>Wed, 27 May 2009 02:25:50 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[flash]]></category>
		<category><![CDATA[flash 3d]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=324</guid>
		<description><![CDATA[My general goal for this was to approximate the look of a video projection hitting a &#8216;non-planar surface&#8217; or otherwise intersecting objects in a 3d scene. The underlying logic wasn&#8217;t too painful. The UV coordinates of each vertex are all that need to be solved for. There&#8217;s a linear relationship between the position and orientation [...]]]></description>
			<content:encoded><![CDATA[<div class="paragraph1">
<div class="imageright"><img src="/blog/assets/ProjectorEffect_t.jpg" onclick="javascript:showBox('ProjectorEffect',780,780, '444444',this);" alt="Thumbnail - Click me" style="cursor: pointer" /></div>
</div>
<p>My general goal for this was to approximate the look of a video projection hitting a &#8216;non-planar surface&#8217; or otherwise intersecting objects in a 3d scene.</p>
<p>The underlying logic wasn&#8217;t too painful. The UV coordinates of each vertex are all that need to be solved for. There&#8217;s a linear relationship between the position and orientation of the &#8216;projector&#8217;, and the world space position and UV coordinates of each vertex in the scene &#8212; requiring just algebra, which is nice, because that&#8217;s about all the math I know. <a href="http://www.jiglibflash.com/" target="_blank">JiglibFlash</a> is being used for the physics action.</p>
<p>In its current implementation, the projector is limited to looking straight down the z-axis. I have a feeling that the most elegant approach for all this would be to extend Camera3D or to piggyback on top of the plumbing of the Papervision framework in some other way (apologies for the mixed metaphor). Should I develop the &#8216;Projection Manager&#8217; to handle arbitrary projector orientation, I&#8217;ll post the source along with an updated example.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/video-projector-effect/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

