<?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>Independent Developer &#187; Code Snippets</title>
	<atom:link href="http://www.independentdeveloper.com/archive/category/code_snippets/feed" rel="self" type="application/rss+xml" />
	<link>http://www.independentdeveloper.com</link>
	<description>Code, Art and Everything In-Between</description>
	<lastBuildDate>Tue, 11 Aug 2009 21:32:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Tower Defense as a Thread Model</title>
		<link>http://www.independentdeveloper.com/archive/2009/06/11/tower-defense-as-a-thread-model</link>
		<comments>http://www.independentdeveloper.com/archive/2009/06/11/tower-defense-as-a-thread-model#comments</comments>
		<pubDate>Thu, 11 Jun 2009 23:28:23 +0000</pubDate>
		<dc:creator>Lisa</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[multicore]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[thread model]]></category>
		<category><![CDATA[tower defense]]></category>
		<category><![CDATA[turret defense]]></category>
		<category><![CDATA[video games]]></category>

		<guid isPermaLink="false">http://www.independentdeveloper.com/?p=614</guid>
		<description><![CDATA[I keep having the strangest reoccurring dream. In my dream, I&#8217;m playing a turret defense game. 1 However, it is no ordinary tower game. It&#8217;s actually a thread process model. In the dream, each turret type represents a thread synchronization mechanism, generally some sort of atomic primitive. The units marching along the paths represent the [...]]]></description>
			<content:encoded><![CDATA[<p>I keep having the strangest reoccurring dream. In my dream, I&#8217;m playing a <a href="http://www.newgrounds.com/portal/search/title/tower%20defense">turret defense</a> game. <sup><a href="#footnote">1</a></sup> <strong>However, it is no ordinary tower game. It&#8217;s actually a thread process model.</strong> In the dream, each turret type represents a thread synchronization mechanism, generally some sort of atomic primitive. The units marching along the paths represent the threads that require synchronization. Most are worker threads calculating a result set, but some may be polling threads reading device updates or doing other jobs. The range circle of each tower and the position of the unit along the path represent states when it is appropriate for the thread to be accessed, either quiescent states or work states where the thread has completed some useful task and has a result ready to be read. If the unit\thread moves out of the turret\synchronization range circle, the thread result is lost or held and operation on the next work cycle begins. Shooting a unit\thread with a turret is a read\synchronization operation and gathers the result.</p>
<p>Yeah, I know, clearly I&#8217;ve had threads on the mind a little too much lately. <img src='http://www.independentdeveloper.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  I&#8217;ve been working on a major refactor of the engine at work and <a href="http://herbsutter.wordpress.com/?s=effective+concurrency">thread synchronization problems are tricky</a>.</p>
<p>Usually when I have dreams like this I wake up in the morning and have a good laugh wondering what the heck I was thinking. This time, however, I think there may be something to it. Now, I&#8217;m not suggesting a design built literally on the model exactly as it is in the dream but I think there are elements that could be useful.</p>
<p><strong>The part that is intriguing about the turret defense thread model is that you can guarantee completion (all units hit) without guaranteeing really very much at all about either the turrets or the units. </strong>The units are not synchronized with each other; in fact, in many tower games faster units can overtake slower ones. A unit does not guarantee a minimum speed&#8211;it may even be allowed to stop entirely on occasion&#8211;although it does guarantee a maximum speed. The turrets are not synchronized with each other, nor do they communicate any information to each. A turret does not guarantee a specific number of units hit, only that it will hit units at a specific rate. A turret also does not guarantee what order it will fire at units in. A unit likewise guarantees nothing about when or by whom it will be hit except that it can be hit when it is within a valid range.</p>
<p>Yet, with a sufficient number of correctly placed turrets all the units will be hit with none escaping. More importantly, most of the time you can have far fewer turrets than units and still complete successfully. The number of turrets required is a simple function of the <em>maximum</em> speed of the turret, the <em>maximum</em> speed of the unit, and the number of times the turret must hit the unit for completion. Placement is trickier, but with a thread model you could surely replicate that with signals. </p>
<p>Fascinating, isn&#8217;t it?</p>
<p>I&#8217;m not sure yet where to go with all this, but it seems like there&#8217;s a useful idea to be gleaned. It&#8217;s not that different that a traditional worker pool, but the lack of communication seems important. I&#8217;m sure there&#8217;s something useful that can be done with this.</p>
<hr/>
<p><em>1. <a name="footnote"></a>For anyone who cares, the specific game seems to be <a href="http://en.wikipedia.org/wiki/Crystal_Defenders">Crystal Defenders</a>, but with some elements of <a href="http://www.ninjakiwi.com/Games/Tower-Defense/Bloons-Tower-Defense-3.html">Bloons Tower Defense 3</a>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.independentdeveloper.com/archive/2009/06/11/tower-defense-as-a-thread-model/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>memcpy_s</title>
		<link>http://www.independentdeveloper.com/archive/2009/05/22/memcpy_s</link>
		<comments>http://www.independentdeveloper.com/archive/2009/05/22/memcpy_s#comments</comments>
		<pubDate>Fri, 22 May 2009 20:55:45 +0000</pubDate>
		<dc:creator>Lisa</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.independentdeveloper.com/?p=471</guid>
		<description><![CDATA[On Friday, an article ran on Slashdot making note that Microsoft is &#8220;banning&#8221; the C function memcpy in favor of the new memcpy_s. While memcpy_s has in truth been around for a while, the notion that it would now generate compiler warnings has created quite an uproar. Some people seem curious as to why so [...]]]></description>
			<content:encoded><![CDATA[<p>On Friday, <a href="http://tech.slashdot.org/article.pl?sid=09/05/15/152213">an article ran on Slashdot</a> making note that Microsoft is &#8220;banning&#8221; the C function memcpy in favor of the new memcpy_s. While memcpy_s has in truth been around for a while, the notion that it would now generate compiler warnings has created quite an uproar. Some people seem curious as to why so many people are upset by what seems a pretty innocuous change. The article author asked if was going to affect anyone&#8217;s creativity. I can assure you that&#8217;s not the concern. </p>
<p><strong>In a nutshell: the problem is you can&#8217;t tape a cupholder to a formula one race car and declare it street legal.</strong> It still doesn&#8217;t have any bumpers, it&#8217;s too low to be safe around other cars, and if you aren&#8217;t an expert driver you still shouldn&#8217;t be driving it. A cupholder doesn&#8217;t change that. </p>
<p><strong>So what? A cupholder is still an improvement&#8230; right?</strong> Who <em>doesn&#8217;t</em> want a cupholder? Imagine for a moment that having the cupholder suddenly disqualified you from a number of races. You couldn&#8217;t run that race if you have a cupholder. It also slowed down your car&#8211;not a lot, but a tiny fraction of a second. Maybe it doesn&#8217;t slow it down enough to matter, but in those few races won by hundredths&#8230; well, maybe it does. Suddenly that cupholder doesn&#8217;t seem so nice.</p>
<p>To be clear, I’m <strong>not</strong> suggesting giving up on attempts to improve memory management and prevent buffer overruns. I just question if this exact approach was the best one.</p>
<p>Memcpy_s is basically a race car with a cupholder. While memcpy_s will certainly prevent some bugs, the same people who got one parameter wrong are just as likely to get two parameters wrong&#8230; and cause <em>all new bugs</em> in the process. <a href="http://en.wikipedia.org/wiki/Garbage_In,_Garbage_Out"><strong>Garbage In = Garbage Out.</strong></a> It doesn&#8217;t matter what the calling convention is.</p>
<blockquote><p>On two occasions I have been asked,—&#8221;Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?&#8221; … I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question.”</p>
<div align="right">— Charles Babbage, 1864<br/>discussing the first mechanical computer</div>
</blockquote>
<p>The change also comes with a price: it breaks cross-compatibility with other compilers, including older compilers on the same operating system as well as other platforms. This means the same code can&#8217;t cross-compile anymore if you use memcpy_s. <a href="http://blogs.msdn.com/sdl/archive/2008/10/22/good-hygiene-and-banned-apis.aspx">Someone with Microsoft suggested that GCC should pick up the change as well.</a> Perhaps, but that assumes that GCC is the only other compiler that matters. Certainly, it&#8217;s the <em>most popular</em> other compiler that matters, but it&#8217;s far from the <em>only</em> one especially if you do embedded systems work or anything running on &#8220;exotic&#8221; hardware. And let&#8217;s be honest&#8211;if you&#8217;re not writing something that&#8217;s fast or exotic, you&#8217;re probably not writing it in C. The exception, of course, being legacy code&#8230; but surely that&#8217;s even less likely to be changed. The whole point of legacy code is that you don&#8217;t have the time\budget to update it, otherwise you wouldn&#8217;t be running it at all. These are the guys who will wrap memcpy_s in a macro named memcpy, defeating it entirely. Sigh.</p>
<p>As for that speed difference I mentioned? We&#8217;re obviously only talking about an extra comparison operator and perhaps a branch or two here. I know an extra comparison operator seems trivial, but if an extra comparison operator didn&#8217;t matter <a href="http://www.acm.uiuc.edu/sigops/roll_your_own/2.a.html">ASSERT</a> macros wouldn&#8217;t exist. The speed difference is nominal, but it&#8217;s very, very real. On a lark I timed it. Copying 32 bytes 100,000 times with memcpy took on average 3952 counts, or about 0.001104 seconds, measured to nanosecond accuracy with QueryPerformanceCounter. Performing the identical operation with memcpy_s took on average 9706 counts, or about 0.002712 seconds. This was in &#8220;release mode&#8221; using Visual Studio 2008. (For the curious, in debug mode the difference averaged 8028 counts to 11340 counts, but you shouldn&#8217;t be shipping your code in debug mode anyway!)</p>
<p>Now hopefully you&#8217;ve done everything you can to avoid memcpy in your inner loop in the first place, but we all know there are rare occasions where it&#8217;s unavoidable. This all brings me back to my earlier point: if you&#8217;re not writing something that&#8217;s fast or exotic, you&#8217;re probably not writing it in C. <strong>Yes, you can write your own memcpy that&#8217;s probably faster than the system memcpy if you&#8217;re really worried about speed, but now we&#8217;re back to the portability issue.</strong> In short, I&#8217;m certain that to the people where the choice of language matters, those few clock cycles matter too. We&#8217;re talking folks writing device drivers here, not business applications. </p>
<p><strong>Nobody is twisting anyone&#8217;s arm to use memcpy_s.</strong> You can easily disable the compiler warnings and continue to use memcpy all you like. But hopefully you see where I&#8217;m going with this: A lot of the reason that people continue to use C for certain projects has to do with performance and portability. This change sacrifices both for dubious return. If the change is not going to have tangible benefits that outweigh the problems, why do it at all? </p>
<p>Sooner or later, you need to trust that the programmer knows what they are doing. If the programmer can&#8217;t manage memory responsibly, you&#8217;ve got a bigger problem than an extra parameter is going to fix. To be honest, while a lot of people don&#8217;t like to admit it programmers sometimes leak or botch memory <a href="http://developers.slashdot.org/article.pl?sid=07/11/17/0552247">even in managed languages.</a> There&#8217;s certainly a thesis paper or two in &#8220;possible alternatives&#8221; to the approach taken&#8211;perhaps checking the block size by querying the allocator instead of asking the programmer which would be even slower but more reliable, borrowing ideas from double entry accounting, etc, etc.&#8211;although the &#8220;real&#8221; fix surely involves more intelligent ways of thinking about memory, <strong>which realistically means a fundamental change in constructs, not a patched function.</strong></p>
<p>As always, <a href="http://xkcd.com/">XKCD</a> sums it up best (panel #2): </p>
<p><img src="http://imgs.xkcd.com/comics/well_2.png" alt="XKCD" /></p>
<p>Ah, I wait for the day&#8230; <img src='http://www.independentdeveloper.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.independentdeveloper.com/archive/2009/05/22/memcpy_s/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Parallel Processing in a Nutshell</title>
		<link>http://www.independentdeveloper.com/archive/2008/08/29/parallel-processing-in-a-nutshell</link>
		<comments>http://www.independentdeveloper.com/archive/2008/08/29/parallel-processing-in-a-nutshell#comments</comments>
		<pubDate>Fri, 29 Aug 2008 20:15:08 +0000</pubDate>
		<dc:creator>Lisa</dc:creator>
				<category><![CDATA[3D Tutorials]]></category>
		<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[1100 barrel]]></category>
		<category><![CDATA[cpu]]></category>
		<category><![CDATA[gpu]]></category>
		<category><![CDATA[multicore]]></category>
		<category><![CDATA[multiprocessing]]></category>
		<category><![CDATA[nvidia]]></category>
		<category><![CDATA[paintball]]></category>

		<guid isPermaLink="false">http://www.independentdeveloper.com/?p=165</guid>
		<description><![CDATA[A friend sent me the link to this video, and I have to say, this is the most clear and direct explanation of the difference between linear processing and concurrent processing I&#8217;ve ever seen. &#8230;That, and it&#8217;s just darn cool to watch a 1100 barrel paintball gun get fired.]]></description>
			<content:encoded><![CDATA[<p>A friend sent me the link to this video, and I have to say, this is the most clear and direct explanation of the difference between linear processing and concurrent processing I&#8217;ve ever seen. &#8230;That, and it&#8217;s just darn cool to watch a <strong>1100 barrel paintball gun</strong> get fired.</p>
<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/fKK933KK6Gg&#038;hl=en&#038;fs=1&#038;rel=0"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/fKK933KK6Gg&#038;hl=en&#038;fs=1&#038;rel=0" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.independentdeveloper.com/archive/2008/08/29/parallel-processing-in-a-nutshell/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BioHacking</title>
		<link>http://www.independentdeveloper.com/archive/2008/03/06/biohacking</link>
		<comments>http://www.independentdeveloper.com/archive/2008/03/06/biohacking#comments</comments>
		<pubDate>Thu, 06 Mar 2008 20:28:29 +0000</pubDate>
		<dc:creator>Lisa</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.independentdeveloper.com/archive/2008/03/06/biohacking</guid>
		<description><![CDATA[If you&#8217;re into reverse engineering biological systems&#8211;in my mind, one of the most fun parts about AI programming&#8211;this talk by Drew Endy is absolutely a blast. Also be sure to check out the BioBricks project at openwetware.org or download the actual &#8220;bricks&#8221; at the MIT Registry of Standard Biological Parts. The BioBricks are sequences of [...]]]></description>
			<content:encoded><![CDATA[<p><center><embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=-6950604815683841321&#038;hl=en" flashvars=""> </embed></center></p>
<p>If you&#8217;re into reverse engineering biological systems&#8211;in my mind, one of the most fun parts about AI programming&#8211;<a href="http://video.google.com/videoplay?docid=-6950604815683841321&#038;hl=en" target="_blank">this talk by Drew Endy</a> is absolutely a blast. Also be sure to check out the <a href="http://openwetware.org/wiki/The_BioBricks_Foundation" target="_blank">BioBricks</a> project at openwetware.org or download the actual &#8220;bricks&#8221; at the <a href="http://parts.mit.edu/registry/index.php/Main_Page" target="_blank">MIT Registry of Standard Biological Parts.</a> </p>
<p>The BioBricks are sequences of DNA described in a standardized, open-source format where each sequence represents a single, interchangeable part or &#8220;device&#8221;. A data sheet is provided for each device that describes what it does and what its tolerances and parameters are, etc., similar to the data sheet for an electronics part. Like an electronic component, devices can be combined together to make more complicated structures. When you&#8217;re finished designing your device, <a href="http://www.google.com/search?hl=en&#038;client=opera&#038;rls=en&#038;hs=xD2&#038;q=dna+sequencing+service&#038;btnG=Search" target="_blank">the sequenced DNA</a> can be inserted as a plasmid into a suitable host cell and used to make all kinds of cool stuff, like <a href="http://parts.mit.edu/registry/index.php/Featured_Parts:Light_Sensor" target="_blank">this biological film</a> where the bacteria change color in response to light. </p>
<div class="photocaption" align="center"><img src="http://openwetware.org/images/8/83/UT_HelloWorld.jpg"><br/><br />
Hello World displayed by light-sensitive, color-changing eColi</div>
]]></content:encoded>
			<wfw:commentRss>http://www.independentdeveloper.com/archive/2008/03/06/biohacking/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>One Dozen Easy C++ Programming Tips</title>
		<link>http://www.independentdeveloper.com/archive/2007/12/12/one-dozen-easy-c-programming-tips</link>
		<comments>http://www.independentdeveloper.com/archive/2007/12/12/one-dozen-easy-c-programming-tips#comments</comments>
		<pubDate>Wed, 12 Dec 2007 16:37:38 +0000</pubDate>
		<dc:creator>Lisa</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[bug tracking]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[crash]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[ui]]></category>
		<category><![CDATA[user interface]]></category>

		<guid isPermaLink="false">http://www.independentdeveloper.com/archive/2007/12/12/one-dozen-easy-c-programming-tips</guid>
		<description><![CDATA[Consistency breeds ease of use. Even if your buttons do some weird thing, as long as they all do the same weird thing users will eventually figure it out. Make the buttons each behave differently, however, and the user is lost forever. Sort data the way it is most likely to be used. The logical [...]]]></description>
			<content:encoded><![CDATA[<ol>
<li>Consistency breeds ease of use. Even if your buttons do some weird thing, as long as they all do the <em>same</em> weird thing users will <em>eventually</em> figure it out. Make the buttons each behave differently, however, and the user is lost forever.</li>
<li>Sort data the way it is most likely to be used. The logical sort order for a date is chronological, not alphabetical. </li>
<li>When in doubt, the default option should be the least destructive \ most undoable choice.</li>
<li>If you have to write an explanation of your code, never assume that the reader has read the same papers you have, unless you told them what else to read&#8211;<em>and where to find it&#8211;</em>first.</li>
<li>Wrong code comments are worse than no code comments.</li>
<li>&#8220;Copy and paste&#8221; errors happen to <em>everyone</em>. Be on the look out for them.</li>
<li>If a bug disappears in debug mode, 90% of the time it will be one of two things: 1) you are overflowing memory or 2) you have a thread race condition. At least two thirds of the time, it will be a memory overflow. It is extremely unlikely it is problem with the compiler.</li>
<li>Releasing your program compiled in &#8220;debug mode&#8221; is not an acceptable &#8220;fix&#8221;. The bug only <em>looks</em> like its gone&#8230; it&#8217;s still there, and can come back to bite you at any time. Don&#8217;t do it, no matter how tempting it might seem.</li>
<li>If the program crashes on exit, you probably freed something you didn&#8217;t properly allocate, or that isn&#8217;t allocated anymore.</li>
<li>Leaking memory is bad. Freeing pointers or objects that don&#8217;t belong to you is worse. If an object you expect to be free is still hanging around, don&#8217;t force it, find out why&#8230; &#8220;fixing&#8221; bugs by patching the symptoms and not the cause makes the code much harder to repair in the long run.</li>
<li>If you have an intermittent bug, and your &#8220;fix&#8221; made it go away and you don&#8217;t know why, the bug is almost certainly still there. If you can&#8217;t explain it, you didn&#8217;t fix it.</li>
<li>Good documentation is more important than more features. Write it down, even if it&#8217;s just a simple &#8220;readme.txt&#8221; file&#8230; the next person who has to work with your stuff will appreciate it!</li>
</ol>
<p>More tips? Ideas you would recommend? Post a comment!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.independentdeveloper.com/archive/2007/12/12/one-dozen-easy-c-programming-tips/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Million Objects</title>
		<link>http://www.independentdeveloper.com/archive/2007/12/09/a-million-objects</link>
		<comments>http://www.independentdeveloper.com/archive/2007/12/09/a-million-objects#comments</comments>
		<pubDate>Sun, 09 Dec 2007 10:43:39 +0000</pubDate>
		<dc:creator>Lisa</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[computer programming]]></category>
		<category><![CDATA[multicore]]></category>
		<category><![CDATA[multithreading]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[zen koan]]></category>

		<guid isPermaLink="false">http://www.independentdeveloper.com/archive/2007/12/09/a-million-objects</guid>
		<description><![CDATA[From a Zen Kōan: Gyosan asked Isan, &#8220;If a million objects come to you, what should you do?&#8221; Isan answered, &#8220;A green object is not yellow. A long object is not short. Each object manages its own fate. Why should I interfere with them?&#8221; Gyosan bowed in homage. It&#8217;s good advice for programming multi-core, too.]]></description>
			<content:encoded><![CDATA[<p>From a <a href="http://www.amazon.com/gp/search?ie=UTF8&#038;keywords=zen%20koans&#038;tag=independevelo-20&#038;index=na-books-us&#038;linkCode=ur2&#038;camp=1789&#038;creative=9325">Zen Kōan</a>:</p>
<blockquote><p>Gyosan asked Isan, &#8220;If a million objects come to you, what should you do?&#8221; Isan answered, &#8220;A green object is not yellow. A long object is not short. Each object manages its own fate. Why should I interfere with them?&#8221; Gyosan bowed in homage.
</p></blockquote>
<p>It&#8217;s good advice for programming multi-core, too.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.independentdeveloper.com/archive/2007/12/09/a-million-objects/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What is Ambient Occlusion?</title>
		<link>http://www.independentdeveloper.com/archive/2007/11/27/what_is_ambient_occlusion</link>
		<comments>http://www.independentdeveloper.com/archive/2007/11/27/what_is_ambient_occlusion#comments</comments>
		<pubDate>Tue, 27 Nov 2007 10:07:00 +0000</pubDate>
		<dc:creator>Lisa</dc:creator>
				<category><![CDATA[3D Tutorials]]></category>
		<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[3d]]></category>
		<category><![CDATA[3d graphics]]></category>
		<category><![CDATA[ambient occlusion]]></category>
		<category><![CDATA[cg]]></category>
		<category><![CDATA[cgi]]></category>
		<category><![CDATA[global illumination]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[monte carlo]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[ray casting]]></category>
		<category><![CDATA[ray tracing]]></category>
		<category><![CDATA[rendering]]></category>
		<category><![CDATA[ssao]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Ambient occlusion is a lighting technique that is commonly used to create soft shadows on objects. Ambient occlusion isn&#8217;t used to create the type of shadows that are cast from objects with a light shining directly on them. Instead, ambient occlusion generates the type of deep shadows that appear in the corners or creases of [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Ambient occlusion</strong> is a lighting technique that is commonly used to create soft shadows on objects. Ambient occlusion isn&#8217;t used to create the type of shadows that are cast from objects with a light shining directly on them. Instead, ambient occlusion generates the type of deep shadows that appear in the corners or creases of things, where it is hard for the light to reach.</p>
<p>Technically speaking, ambient occlusion is a global illumination technique. However, in common usage of the term it is often referred to as a cheap <em>alternative</em> to global illumination. To clear up any confusion, what most renderers refer to as &#8220;global illumination&#8221; is actually an amalgamation of several techniques such as radiosity, metropolis light transport, image-based lighting or photon mapping. The actual techniques used differ slightly from renderer to renderer. Some renderers include an ambient occlusion term as part of their global illumination calculation; others do not.</p>
<p>Like most global illumination techniques, ambient occlusion is dependent on the other geometry in the scene. Ambient occlusion on its own generates less realistic lighting than &#8220;full&#8221; global illumination. However, ambient occlusion is much faster and less complex to calculate than other methods which is why it is still popular among game developers and in production animation.</p>
<p class="photocaption" align="center"><a href="/images/ambient-occlusion.jpg" rel="lightbox" title=""><img src="/images/ambient-occlusion_thumb.jpg" alt="" /></a><br />
(Left) Without Ambient Occlusion. (Right) With Ambient Occlusion<br />
<em>Click for larger image.</em></p>
<p><span id="more-47"></span></p>
<h4>How Does Ambient Occlusion Work?</h4>
<p>To understand how ambient occlusion works, it&#8217;s helpful to break down the terms.</p>
<p>&#8220;Ambient&#8221; refers to the indirect light in the scene. Ambient light is light that doesn&#8217;t come from an identifiable light source. It is light that is accumulated from stray photons bouncing around the room. Photographers sometimes also call this kind of light source &#8220;available light&#8221; or &#8220;existing light&#8221;.</p>
<p>&#8220;Occlusion&#8221; is the act of one object blocking another object. For example, if you are taking a picture and at the last moment a truck drives in front of you blocking the shot, the truck is &#8220;occluding&#8221; your view of your subject. Occlusion is important to computer graphics for many things besides just shadows. For example, many renderers can optimize the scene and render faster by culling objects that are occluded, or hidden, by other objects.</p>
<p>Ambient occlusion is a measurement of how much ambient light is blocked by nearby things. If an object or surface is occluded, less light can reach it, which means the surface will be in shadow. Creases, corners, hollows and the undersides of things tend to have a lot of ambient occlusion.</p>
<h4>For Artists: Rendering with Ambient Occlusion</h4>
<p>Most modern renderers support either some form of global illumination or ambient occlusion; many support both alone or in combination.</p>
<p>Ambient occlusion improves your render by making small details more visible and improving depth perception. A lot of the way humans perceive depth has to do with the size, darkness, and placement of shadows. Using ambient occlusion to add shading to your scene will help the viewer comprehend the placement of objects better.</p>
<p class="photocaption" align="center"><a href="/images/poser-ao.jpg" rel="lightbox" title=""><img src="/images/poser-ao.thumb.jpg" alt="" /></a><br />
Ambient occlusion in Poser 6</p>
<p>While each renderer is different, often the basic concepts are pretty similar between many of them. As an example, here&#8217;s how you can add ambient occlusion to your render in Poser:</p>
<p>- Click to the Materials tab<br />
- Use the eye dropper to select the material you want to edit<br />
- In the Material Properties node editor, click the Set Up Ambient Occlusion Button. This will add an ambient occlusion node to you material shader.</p>
<p>Poser 6 gives you four properties you can adjust on the ambient occlusion node:</p>
<p><strong>Samples</strong> &#8211; The number of ray samples that will be cast. The more rays, the finer the lighting, but the longer the render. Keep this number as low as you can unless the lighting looks splotchy, in which case, turn it up.</p>
<p><strong>MaxDist</strong> &#8211; The maximum distance the ray will test. Larger values generally result in more shadows.</p>
<p><strong>RayBias</strong> &#8211; The smallest distance the ray will test for objects. If you get black blotches on your figure, very slightly increase your ray bias. If you increase it too much, you will start missing shadows, so don&#8217;t turn it up more than you need to.</p>
<p><strong>Strength</strong> &#8211; The blend weight of the effect.</p>
<h4>For Programmers: Implementing Ambient Occlusion</h4>
<p>As far as bang for the buck, ambient occlusion is one of the fastest ways to improve the quality of your game&#8217;s lighting without a tremendous amount of pain. There are many, many algorithms out there for calculating ambient occlusion and each has advantages and disadvantages depending on your engine features. That said, there are two methods in particular I&#8217;d like to point out.</p>
<p><strong>Monte Carlo Ray Casting Method</strong><br />
I&#8217;m not sure if this is the <em>oldest</em> method for calculating ambient occlusion or not, but it was certainly the first method learned. Assuming you already have some sort of ray-triangle collision code, this method is very easy to understand and implement.</p>
<p>For each point you want to calculate lighting for, shoot out a number of random rays. (In truth, you don&#8217;t really want <em>completely</em> random rays&#8230; small random offsets from your surface normal seem to work best.) If the ray hits something, increase the shadow value proportional to the distance along the ray where the collision occurred.</p>
<p>With enough samples per point, this method can produce very good results. The downside is that this method can be very slow. Many games utilizing this method don&#8217;t calculate the ambient occlusion in real-time&#8230; the ambient occlusion is calculated when the level is loaded or off-line when the level is built, and the results are stored in a texture map.</p>
<p><em>[Incidentally... yes... looking at Poser's settings, I'm guessing this or something very similar is the method they are using!]</em></p>
<p><strong>Screen Space Method</strong><br />
Screen space ambient occlusion has been generating a lot of buzz lately. Screen space rendering methods in general are always desirable to real-time programmers because they run in constant time and constant memory, and aren&#8217;t inhibited by scene complexity. A good starting point for learning about screen space ambient occlusion is <a href="http://delivery.acm.org/10.1145/1290000/1281671/p97-mittring.pdf?key1=1281671&amp;key2=9942678811&amp;coll=ACM&amp;dl=ACM&amp;CFID=15151515&amp;CFTOKEN=6184618" title="Siggraph Paper" target="_blank">Martin Mittring of Crytek&#8217;s Siggraph 2007 presentation</a>.</p>
<p>Basically, the notion is that by sampling surrounding points in the depth buffer you can estimate shadowed areas. Think of it (sort of) like running an edge-detection routine on the z-buffer. The method can produce some artifacts, but there are number of ways to combat them&#8230; and the benefit of course is that this method is fast even on complex scenes.</p>
<p>Again, there are many methods out there and numerous variations, but hopefully this is enough to get you pointed in the right direction!</p>
<p>Questions? Ideas? Links to your favorite method? Post a comment!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.independentdeveloper.com/archive/2007/11/27/what_is_ambient_occlusion/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Finger Tracking with Wii Remote</title>
		<link>http://www.independentdeveloper.com/archive/2007/11/13/finger_tracking_with_wii_remot</link>
		<comments>http://www.independentdeveloper.com/archive/2007/11/13/finger_tracking_with_wii_remot#comments</comments>
		<pubDate>Tue, 13 Nov 2007 07:22:00 +0000</pubDate>
		<dc:creator>Lisa</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[finger tracking]]></category>
		<category><![CDATA[johnny lee]]></category>
		<category><![CDATA[multipoint]]></category>
		<category><![CDATA[nintendo]]></category>
		<category><![CDATA[remote]]></category>
		<category><![CDATA[ui]]></category>
		<category><![CDATA[user interface]]></category>
		<category><![CDATA[wii]]></category>
		<category><![CDATA[wiimote]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Johnny Lee shares a simple but clever approach for implementing finger tracking with the Wii remote: [youtube:http://www.youtube.com/watch?v=0awjPUkBXOU 350 292]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.cs.cmu.edu/~johnny/data/index.html">Johnny Lee</a> shares a simple but clever approach for implementing finger tracking with the Wii remote:</p>
<p align="center">[youtube:http://www.youtube.com/watch?v=0awjPUkBXOU 350 292]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.independentdeveloper.com/archive/2007/11/13/finger_tracking_with_wii_remot/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Content Aware Image Resizing</title>
		<link>http://www.independentdeveloper.com/archive/2007/10/30/content_aware_image_resizing</link>
		<comments>http://www.independentdeveloper.com/archive/2007/10/30/content_aware_image_resizing#comments</comments>
		<pubDate>Tue, 30 Oct 2007 07:48:00 +0000</pubDate>
		<dc:creator>Lisa</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[algorithms]]></category>
		<category><![CDATA[computer graphics]]></category>
		<category><![CDATA[computer programming]]></category>
		<category><![CDATA[content aware]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[image resizing]]></category>
		<category><![CDATA[image retargeting]]></category>
		<category><![CDATA[image scaling]]></category>
		<category><![CDATA[research]]></category>
		<category><![CDATA[siggraph]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[A friend at work just showed me this, and boy is it cool. &#8220;Seam Carving&#8221; is a new algorithm for image retargeting. Image retargeting is an alternative to scaling and cropping, but it is content-aware. Scaled images suffer from the problem that the re-sized content may be too small to see. Cropped images may eliminate [...]]]></description>
			<content:encoded><![CDATA[<p>A friend at work just showed me this, and boy is it cool. <strong>&#8220;Seam Carving&#8221;</strong> is a new algorithm for image retargeting. Image retargeting is an alternative to scaling and cropping, but it is content-aware. Scaled images suffer from the problem that the re-sized content may be too small to see. Cropped images may eliminate important content. Image retargeting solves both problems by keeping the image elements the same size and simply eliminating the &#8220;unimportant&#8221; parts of the image.</p>
<p>Graphic artists occasionally modify images this way by hand when doing page layouts for magazines&#8211;think of it like a visual form of copy-fitting&#8211;but an automated approach opens a world of possibilities. The number of of potential practical applications are immense, and include everything from dynamic web page re-flowing to widescreen-to-standard aspect texture fitting for games.</p>
<p align="center">
[youtube:http://www.youtube.com/watch?v=vIFCV2spKtg 350 292]<br />
<strong>A <a href="http://www.faculty.idc.ac.il/arik/IMRet-All.mov" title="Seam Carving Video" target="_blank">better version of the video</a> as well as the <a href="http://www.faculty.idc.ac.il/arik/imret.pdf" title="Seam Carving for Content-Aware Image Resizing" target="_blank">research paper</a> can be found on <a href="http://www.faculty.idc.ac.il/arik/" title="Dr. Shamir's Research" target="_blank">Dr. Shamir&#8217;s</a> home page</strong>. What&#8217;s really neat is how straight-forward the method seems to be. The paper is well worth the read if you are interested in graphics algorithms.</p>
<p>If you&#8217;d like to play around with this technique on your own images, <strong>someone&#8217;s already <a href="http://rsizr.com/" title="Flash Image Retargeting" target="_blank">implemented the algorithm in Flash</a>.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.independentdeveloper.com/archive/2007/10/30/content_aware_image_resizing/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="http://www.faculty.idc.ac.il/arik/IMRet-All.mov" length="17942449" type="video/quicktime" />
		</item>
		<item>
		<title>Export Outlook Task Lists</title>
		<link>http://www.independentdeveloper.com/archive/2007/10/26/export_outlook_task_lists</link>
		<comments>http://www.independentdeveloper.com/archive/2007/10/26/export_outlook_task_lists#comments</comments>
		<pubDate>Fri, 26 Oct 2007 08:36:00 +0000</pubDate>
		<dc:creator>Lisa</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[computer programming]]></category>
		<category><![CDATA[dasl]]></category>
		<category><![CDATA[e-mail]]></category>
		<category><![CDATA[exchange]]></category>
		<category><![CDATA[flagged]]></category>
		<category><![CDATA[follow-up]]></category>
		<category><![CDATA[imap]]></category>
		<category><![CDATA[macro]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[outlook]]></category>
		<category><![CDATA[task list]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Outlook 2007 has a very cool feature that lets you embed your current calendar in an e-mail and send it someone else. Wouldn&#8217;t it be nice if you could e-mail your To-Do list as well? Now you can! This macro shows you how to generate a formatted e-mail that contains all of your current tasks, [...]]]></description>
			<content:encoded><![CDATA[<p>Outlook 2007 has a very cool feature that lets you embed your current calendar in an e-mail and send it someone else. Wouldn&#8217;t it be nice if you could e-mail your To-Do list as well? Now you can! This macro shows you how to generate a formatted e-mail that contains all of your current tasks, as well as a list of any messages that you&#8217;ve flagged for follow-up.</p>
<p><span id="more-25"></span></p>
<p><strong>To use this macro</strong>, copy and paste the code below into ThisOutlookSession. (Careful! Don&#8217;t overwrite other stuff that might already be in there.) You can access ThisOutlookSession from Tools &gt; Macro &gt; Visual Basic Editor. You must have Visual Basic for Applications installed; this is normally installed as part of Office.</p>
<p><strong><a href="/files/vba-outlook-exporttasklist.txt" title="download source">Download the source code.</a></strong></p>
<p class="codeblock"><strong>Function GetEmailsMarkedForFollowUp(myOlFolder As Outlook.Folder)</strong><br />
Dim objTable As Outlook.Table<br />
Dim objRow As Outlook.Row<br />
Dim strFilter As String<br />
Dim strReturn As String<br />
Dim myObjSubFolder As Outlook.Folder<br />
Dim intCurrent As Integer</p>
<p><span class="codecomment">&#8216; ignore certain folders in the interest of having outlook return sometime in the foreseeable future</span><br />
If (myOlFolder.Name = &#8220;Trash&#8221;) Or (myOlFolder.Name = &#8220;Archive&#8221;) Or (myOlFolder.Name = &#8220;Junk&#8221;) Or (myOlFolder.Name = &#8220;Junk E-mail&#8221;) Then<br />
GetEmailsMarkedForFollowUp = &#8220;&#8221;<br />
Exit Function<br />
End If</p>
<p><span class="codecomment">&#8216; clear string</span><br />
strReturn = &#8220;&#8221;</p>
<p><span class="codecomment">&#8216; Define a DASL filter that finds items marked for follow-up</span><br />
strFilter = &#8220;@SQL=&#8221; &amp; Chr(34) &amp; &#8220;<a href="http://schemas.microsoft.com/mapi/proptag/0x0E2B0003">http://schemas.microsoft.com/mapi/proptag/0x0E2B0003</a>&#8221; &amp; Chr(34) &amp; &#8221; = 1&#8243;</p>
<p><span class="codecomment">&#8216; construct a table of items using the filter</span><br />
Set objTable = myOlFolder.GetTable(strFilter)</p>
<p>With objTable</p>
<p><span class="codecomment">&#8216; Add task-related columns to the table.</span><br />
.Columns.Add (&#8220;TaskDueDate&#8221;) <span class="codecomment">&#8216; this always seems to be blank in imap, but might be useful if you use exchange</span><br />
.Columns.Add (&#8220;Subject&#8221;)<br />
.Columns.Add (&#8220;Categories&#8221;)<br />
.Columns.Add (&#8220;SenderName&#8221;)</p>
<p><span class="codecomment">&#8216; add flagged e-mails to the formatted task string</span><br />
Do Until .EndOfTable<br />
Set objRow = .GetNextRow</p>
<p>strReturn = strReturn &amp; &#8220;&lt;div style=&#8221;"margin: 0; padding: 0; width: 100%; font-size: .85em; font-family: Verdana; background-color: #EDEDED;&#8221;"&gt;&#8221;<br />
strReturn = strReturn &amp; objRow(&#8220;Subject&#8221;) &amp; &#8220;&lt;/div&gt;&lt;div style=&#8221;"margin: 0; padding: 0;&#8221;"&gt;&#8221;<br />
strReturn = strReturn &amp; &#8220;&lt;span style=&#8221;"font-size: .75em;&#8221;"&gt;&lt;b&gt;From:&lt;/b&gt; &#8221; &amp; objRow(&#8220;SenderName&#8221;) &amp; &#8220;&lt;/span&gt;&lt;br/&gt;&#8221;<br />
strReturn = strReturn &amp; &#8220;&lt;span style=&#8221;"font-size: .75em;&#8221;"&gt;&lt;b&gt;Category:&lt;/b&gt; &#8221; &amp; objRow(&#8220;Categories&#8221;) &amp; &#8220;&lt;/span&gt;&lt;br/&gt;&#8221;<br />
strReturn = strReturn &amp; &#8220;&lt;br/&gt;&lt;/div&gt;&#8221;<br />
Loop<br />
End With</p>
<p><span class="codecomment">&#8216; clean up</span><br />
Set objRow = Nothing<br />
Set objTable = Nothing</p>
<p><span class="codecomment">&#8216; check subfolders</span><br />
intCurrent = 1<br />
While intCurrent &lt; myOlFolder.Folders.count<br />
strReturn = strReturn &amp; GetEmailsMarkedForFollowUp(myOlFolder.Folders.Item(intCurrent))<br />
intCurrent = intCurrent + 1<br />
Wend</p>
<p><span class="codecomment">&#8216; return the result</span><br />
GetEmailsMarkedForFollowUp = strReturn<br />
<strong>End Function</strong></p>
<p><strong>Sub CreateToDoMail(strAccountName As String)</strong><br />
Dim myOlApp As New Outlook.Application<br />
Dim myOlNameSpace As Outlook.NameSpace<br />
Dim objTaskFolder As Outlook.Folder<br />
Dim myObjTask As Outlook.TaskItem<br />
Dim myObjMail As Outlook.MailItem<br />
Dim strEmailBody As String</p>
<p><span class="codecomment">&#8216; get the task list</span><br />
Set myOlNameSpace = myOlApp.GetNamespace(&#8220;MAPI&#8221;)<br />
Set objTaskFolder = myOlNameSpace.GetDefaultFolder(olFolderTasks)</p>
<p><span class="codecomment">&#8216; add each task item to an html-formatted list</span><br />
strEmailBody = &#8220;&lt;h3 style=&#8221;"font-family: Verdana; padding: 0: margin: 0&#8243;&#8221;&gt;Tasks&lt;/h3&gt;&#8221;<br />
For Each myObjTask In objTaskFolder.Items<br />
If Not myObjTask.Complete Then<br />
strEmailBody = strEmailBody &amp; &#8220;&lt;div style=&#8221;"margin: 0; padding: 0; width: 100%; font-size: .85em; font-family: Verdana; background-color: #EDEDED;&#8221;"&gt;&#8221;<br />
If myObjTask.Importance = 2 Then<br />
strEmailBody = strEmailBody &amp; &#8220;&lt;span style=&#8221;"font-weight: bold; color: red;&#8221;"&gt;!&lt;/span&gt; &#8221;<br />
End If<br />
strEmailBody = strEmailBody &amp; myObjTask.Subject &amp; &#8220;&lt;/div&gt;&lt;div style=&#8221;"margin: 0; padding: 0;&#8221;"&gt;&#8221;<br />
strEmailBody = strEmailBody &amp; &#8220;&lt;span style=&#8221;"font-size: .75em;&#8221;"&gt;&lt;b&gt;Date due:&lt;/b&gt; &#8221; &amp; myObjTask.DueDate &amp; &#8220;&lt;/span&gt;&lt;br/&gt;&#8221;<br />
strEmailBody = strEmailBody &amp; &#8220;&lt;span style=&#8221;"font-size: .75em;&#8221;"&gt;&lt;b&gt;Category:&lt;/b&gt; &#8221; &amp; myObjTask.Categories &amp; &#8220;&lt;/span&gt;&lt;br/&gt;&#8221;<br />
strEmailBody = strEmailBody &amp; &#8220;&lt;br/&gt;&lt;/div&gt;&#8221;<br />
End If<br />
Next</p>
<p><span class="codecomment">&#8216; also add mail items that have been marked for follow-up</span><br />
strEmailBody = strEmailBody &amp; &#8220;&lt;h3 style=&#8221;"font-family: Verdana; padding: 0: margin: 0&#8243;&#8221;&gt;&lt;br/&gt;Mail Items Marked for Follow-Up&lt;/h3&gt;&#8221;<br />
strEmailBody = strEmailBody &amp; GetEmailsMarkedForFollowUp(myOlNameSpace.Folders(strAccountName))</p>
<p><span class="codecomment">&#8216; create a new html e-mail message</span><br />
Set myObjMail = myOlApp.CreateItem(olMailItem)<br />
myObjMail.Subject = &#8220;My To-Do List: &#8221; &amp; Date<br />
myObjMail.BodyFormat = olFormatHTML<br />
myObjMail.HTMLBody = strEmailBody<br />
myObjMail.Display<br />
<strong>End Sub</strong></p>
<p>After you have added the macro, you can assign it to a button by right-clicking within Outlook and selecting &#8220;Customize&#8221;. This macro is designed to handle multiple e-mail accounts, so you&#8217;ll need to add a stub function for each account if you want to add it to a button, like so:</p>
<p class="codeblock"><strong>Sub ExportMyToDoList()</strong><br />
CreateToDoMail &#8220;yourname@yourdomain.com&#8221; <span class="codecomment">&#8216; fill this in with your e-mail address</span><br />
<strong>End Sub</strong></p>
<p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &#8220;AS IS&#8221; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.independentdeveloper.com/archive/2007/10/26/export_outlook_task_lists/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
