<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-23430315</id><updated>2012-01-30T17:49:33.007-08:00</updated><category term='source code'/><category term='John Ratcliff'/><category term='CreateDynamics'/><category term='snippets'/><category term='PhysXViewer'/><category term='Code Suppository'/><category term='Automatic Generation of Dynamics Models'/><category term='GDC 2007'/><category term='physics assets'/><category term='GDC'/><category term='game physics'/><title type='text'>John Ratcliff's Code Suppository</title><subtitle type='html'>A place where I insert my code into the anus of the Internet.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default?start-index=101&amp;max-results=100'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>114</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-23430315.post-1663944264369383724</id><published>2011-12-09T14:20:00.001-08:00</published><updated>2011-12-09T14:21:30.485-08:00</updated><title type='text'>New Implementation of the HACD Algorithm : Julio Jerez</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-1qQzcastB2Q/TuEqoLnq9kI/AAAAAAAAH8M/F31l6IcqkDo/s1600/photographs_pictures_2011_Winston_IMG_3241.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/-1qQzcastB2Q/TuEqoLnq9kI/AAAAAAAAH8M/F31l6IcqkDo/s400/photographs_pictures_2011_Winston_IMG_3241.jpg" width="266" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;So, it turns out that Julio Jerez, author of the Newton Physics Engine, did his own implementation of Khaled Mamou's HACD algorithm (hierarchical approximate convex decomposition).&lt;br /&gt;&lt;br /&gt;The big problem with Khaled's version is that it was extremely slow due to how he went about performing a distance calculation.&amp;nbsp; Julio's implementation does not suffer from this, and is much, much faster.&lt;br /&gt;&lt;br /&gt;In addition, I added my own merge-hulls code as an optional post process step.&lt;br /&gt;&lt;br /&gt;You can download the new version from this &lt;a href="https://code.google.com/p/hacd/"&gt;Google Code Project page.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Once you are synced you can try running say the complex segmented bug model.&lt;br /&gt;&lt;br /&gt;Run: TestHACD hornbug.obj&lt;br /&gt;&lt;br /&gt;This will produce a 58 convex hull model saved out to the file 'ConvexDecomposition.obj'&lt;br /&gt;&lt;br /&gt;If you want one that is even more precision you can try something like:&lt;br /&gt;&lt;br /&gt;TestHACD hornbug.obj -c 0.1&lt;br /&gt;&lt;br /&gt;This sets the concavity value to 0.1 from the default of 0.2.&lt;br /&gt;&lt;br /&gt;This will produce 73 convex hulls.&lt;br /&gt;&lt;br /&gt;However, if you want to run the post-process merge phase, you can reduce the number of hulls by the following.&lt;br /&gt;&lt;br /&gt;Run: TestHACD hornbug.obj -m 40&lt;br /&gt;&lt;br /&gt;That will recursively collapse the convex hulls (starting with the smallest to the largest) until there are no more than 40 hulls left.&lt;br /&gt;&lt;br /&gt;Take a look at the resulting file 'ConvexDecomposition.obj' and you will see how nicely the convex hulls were collapsed.&lt;br /&gt;&lt;br /&gt;This version is *extremely* fast and can be used even on meshes with high vert counts without taking forever.&lt;br /&gt;&lt;br /&gt;While, in general, Julio's implementation seems to be working great, we have found a couple of edge cases it fails on.&lt;br /&gt;&lt;br /&gt;In the project you will find two wavefront OBJ files, 'box-thick.obj' and 'cylinder.obj'.&lt;br /&gt;&lt;br /&gt;'Box-thick.obj' is a hollowed out box, which Khaled's implementation handles correctly, but Julio's fails on.&amp;nbsp; Same thing for the cylinder.&lt;br /&gt;&lt;br /&gt;Hopefully we can get this tracked down soon.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;To use this source code in your own project, just copy the sources from the sub-directory 'hacd'.&amp;nbsp; The rest of your application only needs access to the folder 'hacd\public'.&lt;br /&gt;&lt;br /&gt;Modify the header file 'PlatformConfigHACD.h' to change the global memory allocation routines if you want them to vector to your own methods.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-1663944264369383724?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='https://code.google.com/p/hacd/' title='New Implementation of the HACD Algorithm : Julio Jerez'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/1663944264369383724/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=1663944264369383724' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1663944264369383724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1663944264369383724'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2011/12/new-implementation-of-hacd-algorithm.html' title='New Implementation of the HACD Algorithm : Julio Jerez'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-1qQzcastB2Q/TuEqoLnq9kI/AAAAAAAAH8M/F31l6IcqkDo/s72-c/photographs_pictures_2011_Winston_IMG_3241.jpg' height='72' width='72'/><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-5504409762463038249</id><published>2011-11-03T15:41:00.000-07:00</published><updated>2011-11-03T17:03:04.286-07:00</updated><title type='text'>GatherPictures : A console app to gather all JPEG files into one location without duplicates</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-PZA7HWhlGp4/TrMSzWOnE7I/AAAAAAAAHyM/06ej9hHvBYE/s1600/winston.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="295" src="http://1.bp.blogspot.com/-PZA7HWhlGp4/TrMSzWOnE7I/AAAAAAAAHyM/06ej9hHvBYE/s400/winston.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Today I'm providing a little console application that I wrote for my own personal needs.&amp;nbsp; On the theory that if I found it useful, probably some other people might find it useful too, I'm making it available here.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The tool is provided as a &lt;a href="http://www.duatiu.com/GatherPictures.zip"&gt;ZIP file&lt;/a&gt;.&amp;nbsp; It includes both the source code and the Windows console application.&amp;nbsp; It is designed to be run from the command line, so if you are a Windoze user, this might not be the tool for you.&lt;br /&gt;&lt;br /&gt;So, here is the problem I was trying to solve.&amp;nbsp; I think many other people may have this problem too.&amp;nbsp; Over the years you transfer files from various memory cards, digital cameras or Iphones.&amp;nbsp; You have them on a bunch of different places on your hard drive.&amp;nbsp; You have them on your computer, you have them on your wife's computer you have them on old CD-ROMs or external USB drives.&lt;br /&gt;&lt;br /&gt;Then, one day, you would like to simply get a copy of all the photographs you have scattered around all these locations into one spot, without any binary duplicates.&amp;nbsp; This tool does not do an inexact match, it won't detect images which are the same, but at different resolution or have been cropped or rotated.&amp;nbsp; There are commercial tools that can perform this operation fairly well.&amp;nbsp; Personally I use &lt;a href="http://www.mindgems.com/products/VS-Duplicate-Image-Finder/VSDIF-About.htm"&gt;Visual Similarity Duplicate Image Finder.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This tool also does not do image resizing, there are many commercial tools that can do that as well.&lt;br /&gt;&lt;br /&gt;What the tool is designed to do is collect all of my pictures, from many different sources, into one single flat directory so that I can then, easily, run these commercial tools on them to create a nice clean set of non-duplicate images ready to be copied onto a memory card to put into a digital picture frame.&lt;br /&gt;&lt;br /&gt;There is nothing particularly special or magical about this source code.&amp;nbsp; It's nothing I'm proud of in any particular way, it's just something I hacked up real quick and seems to work.&lt;br /&gt;&lt;br /&gt;Now, here is how you use the tool.&amp;nbsp; Let's say you have a bunch of pictures in a directory called 'MyPhotographs' and under that directory are many sub-directories.&amp;nbsp; Now, let's say you have another directory called 'WifesPhotographs' which may, or may not, have some of the same pictures duplicated.&lt;br /&gt;&lt;br /&gt;The way to use this tool is you create a folder where you want to 'gather' these images into.&lt;br /&gt;&lt;br /&gt;Next, go to that directory and at the command prompt and run the GatherPictures.exe (should be placed somewhere that your default search path can find):&lt;br /&gt;&lt;br /&gt;GatherPictures c:\MyPhotographs&lt;br /&gt;&lt;br /&gt;This will find all JPG files in that directory and all sub-directories and copy them into your current directory giving each image a unique flat file name.&lt;br /&gt;&lt;br /&gt;For example, if you had an image 'c:\MyPhotographs\vacation\img001.jpg'&lt;br /&gt;&lt;br /&gt;It would get copied as the file name 'MyPhotographs_vacation_img001.jpg'&lt;br /&gt;&lt;br /&gt;If after running 'GatherPictures' against 'c:\MyPhotographs' you run it a second time, then it will detect that all the files are the same and it won't copy anything.&amp;nbsp; On the other hand, if new photographs get added to that directory, it will detect the new ones and pick them up.&lt;br /&gt;&lt;br /&gt;You can continue to run 'GatherPictures' against any directory and it will avoid copying any binary duplicates.&lt;br /&gt;&lt;br /&gt;Once you have 'gathered' all of your pictures you may find that you have gigs and gigs of photographs.&amp;nbsp; For example, I had about 50gb of photographs in 38,000 files.&amp;nbsp; One of the issues I ran into is that when I tried to run some image processing tools on this directory they crashed because they had never been designed to handle that many images.&amp;nbsp; Also, there is the use case where you might want to break these up into say 8gb or 16gb chunks suitable for copying onto a memory card.&lt;br /&gt;&lt;br /&gt;I added a new feature to 'GatherPictures' which will take all of the pictures in the source directory and copy them into sub-directories of a specified size limit.&amp;nbsp; The original pictures are left alone.&lt;br /&gt;&lt;br /&gt;The usage for this is:&lt;br /&gt;&lt;br /&gt;GatherPictures -split &lt;size in="" megabytes=""&gt;&lt;/size&gt;&lt;br /&gt;&lt;br /&gt;So, if you wanted to split all files into 1gb sub-folders you would use:&lt;br /&gt;&lt;br /&gt;GatherPictures -split 1024&lt;br /&gt;&lt;br /&gt;(A gigabyte is 1,024 megabytes)&lt;br /&gt;&lt;br /&gt;For those who are interested, here is how the code works.&lt;br /&gt;&lt;br /&gt;At start up the first thing it does is scan all JPG files in the current directory.&amp;nbsp; It examines the size of each file and places it into a hash map.&amp;nbsp; It also builds a hash map of all file names.&lt;br /&gt;&lt;br /&gt;Next, after scanning all of the files in the source directory, it does the following.&lt;br /&gt;&lt;br /&gt;First, it makes sure the file name doesn't match one that has already been gathered.&amp;nbsp; It uses the previously built hash map to speed this up.&amp;nbsp; If it matches, it skips it.&lt;br /&gt;&lt;br /&gt;If the file name doesn't match it then looks up the binary file size against the hash map of files by size.&amp;nbsp; If there is already one, or more, files of that exact size it then tests to see if it is or is not duplicate.&lt;br /&gt;&lt;br /&gt;First, it reads the source file into memory and computes a 32 bit CRC.&amp;nbsp; Next it compares that CRC to the CRC of the previously registered files.&amp;nbsp; If it is the first time the file has been checked, it has to read the file into memory to compute the CRC.&amp;nbsp; However, it caches the CRC so this is only done once.&amp;nbsp; The next time it encounters a file of this same size, it can just use the cached CRC for an early reject.&lt;br /&gt;&lt;br /&gt;If the CRCs match only then does it do an exact binary memory compare to see if the two files are, in fact, exactly identical.&lt;br /&gt;&lt;br /&gt;Let me know if you find the tool useful or can think of improvements.&amp;nbsp; As I said, my goal was not to replace the functionality of commercial duplicate image finder tools but, rather, I just wanted a way to collate all my image files into one single location giving each file a unique file name based on it's original source directory location.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-5504409762463038249?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.duatiu.com/GatherPictures.zip' title='GatherPictures : A console app to gather all JPEG files into one location without duplicates'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/5504409762463038249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=5504409762463038249' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/5504409762463038249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/5504409762463038249'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2011/11/gatherpictures-console-app-to-gather.html' title='GatherPictures : A console app to gather all JPEG files into one location without duplicates'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-PZA7HWhlGp4/TrMSzWOnE7I/AAAAAAAAHyM/06ej9hHvBYE/s72-c/winston.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-8493129812237369040</id><published>2011-08-28T11:30:00.000-07:00</published><updated>2011-08-29T06:56:38.265-07:00</updated><title type='text'>Don't look a gift horse in the mouth</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-lAuX_I_zATA/Tlp7m5TkktI/AAAAAAAAHxk/UNQm0u_Lfnk/s1600/horse-mouth2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="300" src="http://3.bp.blogspot.com/-lAuX_I_zATA/Tlp7m5TkktI/AAAAAAAAHxk/UNQm0u_Lfnk/s400/horse-mouth2.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;My friend&lt;a href="http://www.cbloom.com/rants.html"&gt; Charles Bloom&lt;/a&gt; likes to rant on his blog, and I often envy him. &amp;nbsp;He lets his inner id loose in a way few others do. Personally I don't let out a good rant that often but, tonight I will.&lt;br /&gt;&lt;br /&gt;Now, earlier in the evening I must admit that I had a few drinks and I also admit that as a rule most of my public rants are fueled by exactly that kind of behavior.  But, tonight I don't think that has anything to do with it.&lt;br /&gt;&lt;br /&gt;This blog is called the 'code suppository' for a reason. It is the place where I insert my computer software into the anus of the internet.&lt;br /&gt;&lt;br /&gt;Now, I release open source code for a number of reasons.  Let me take this opportunity to say what they are and in order of importance.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-large;"&gt;(1)&lt;/span&gt;&lt;/b&gt; The number one reason is that I do it for myself.  Like many programmers I have my 'bag of tricks' code snippets which I use over and over again.  No one wants to keep writing the same parser,&lt;br /&gt;or similar piece of utility code over and over again.  Many long time C++ programmers accumulate a personal library of goodies over the years and, frankly we publish the source for ourselves as much as anyone else.  Chances are I personally go back to the code snippets hosted on this site probably more often than anyone else.&amp;nbsp; I never want to ever again have to write from scratch how to compute the nearest intersection point between a line segment and another arbitrary 3d point in space.&amp;nbsp; I never want to write again form scratch code to read a .INI file, handle key-value spec properties, parse an XML file, etc. etc.&amp;nbsp; So, I post those code snippets primarily for my own use.&amp;nbsp; If anyone else finds them useful, that is just a bonus.&amp;nbsp; This is, I believe, pretty much what my friend &lt;a href="http://nothings.org/"&gt;Sean Patrick Barret&lt;/a&gt; does.&amp;nbsp; Sean is an incredibly generous guy who has released more useful free source code snippets used by more people than almost anyone else out there.&amp;nbsp; For example, I think Sean's PNG reader/writer code has probably found its way into literally thousands and thousands of software projects.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-large;"&gt;(2)&lt;/span&gt;&lt;/b&gt; The second but, to me, the most important reason that I publish open code  source is out of a sense of moral obligation.  Over my 30+ years as a professional software developer I have benefited greatly hundreds, if not thousands, of times from the open source work of others.  And when I say 'open source I don't mean that  bullshit GPL garbage. I mean really, truly &lt;b&gt;free &lt;/b&gt;open source conforming to the BSD/MIT license.  Truly free source code in every way with with no restrictions on it other than "you can't sue me if it doesn't work."&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-large;"&gt;(3)&lt;/span&gt;&lt;/b&gt; The third reason I release stuff open source is in the hopes that some other programmer might find bugs in the code and contribute fixes and/or improvements.&amp;nbsp; There is no better example of this than when Khaled Mamou took my approximate convex decomposition algorithm and used it as inspiration for his dramatically improved hierarchical convex decomposition code &lt;a href="http://codesuppository.blogspot.com/2011/05/hacd-hierarchical-approximate-convex.html"&gt;HACD&lt;/a&gt;.&amp;nbsp; It gives me a tremendous amount of satisfaction that my work inspired someone to do something even better.&amp;nbsp; And, guess what, I'm returning the favor by optimizing HACD so that it will run several orders of magnitude faster than it does today.&amp;nbsp; This process of using open source to work together as a community, helping one another out, is something I find very gratifying to be a part of.&amp;nbsp; Or, at least *used* to find gratifying...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-large;"&gt;(4)&lt;/span&gt;&lt;/b&gt; The fourth and final reason that I release open source code is for educational purposes.&amp;nbsp; I think of it as a service to the community and also as an educational exercise.&amp;nbsp; Over the years, when I have tried to get something useful in terms of available open source code I have often run into major challenges trying to extract just the specific piece of functionality that I want.&amp;nbsp; Many software engineers write their code on top of rather massive template libraries; especially for data structures and mathematics.&amp;nbsp; So, if you want to get just a particular routine (like say computing the best fit plane equation to a collection of 3d samples), you cannot simply get just that routine.&amp;nbsp; Instead, you have to adopt 50 to 100 thousand lines of source code, including a massive library and template framework to get access to that functionality.&amp;nbsp; This isn't a problem if you want their whole library, but it is is a problem if you just want that one routine or want to refactor it to work with your own data structures and math template library.&lt;br /&gt;&lt;br /&gt;My goal is to help educate the public in what I personally believe is the ideal way to share source code with others over the Internet; as 'code snippets'.&amp;nbsp; With most of my releases I try to set a good example and educate others.&amp;nbsp; I have received enough positive feedback over the years to know that a lot of people really do appreciate it.&lt;br /&gt;&lt;br /&gt;Now, it's time to get back to the rant.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I have edited this post from it's original and will replace that content with one simple request.&lt;br /&gt;&lt;br /&gt;If someone gives away free open source, and you have questions, feedback, or suggestions for improvements, please send a polite and friendly email to the author.&amp;nbsp; Chances are that author will try to be of help.&amp;nbsp; If you send the author a rude and insulting email, that's probably not going to be very helpful or put them in a mood to help you.&lt;br /&gt;&lt;br /&gt;Also, if you don't get an answer to your email, don't be upset right away.&amp;nbsp; Like many people on the Internet, authors of open source work can receive hundreds of email a day, and it's easy for one of them to either get marked as spam or the person intends to give a reply, but it slips through the cracks.&lt;br /&gt;&lt;br /&gt;And, as your mother always said, if you have nothing nice to say, you can always say nothing at all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-8493129812237369040?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/8493129812237369040/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=8493129812237369040' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8493129812237369040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8493129812237369040'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2011/08/dont-look-gift-horse-in-mouth.html' title='Don&apos;t look a gift horse in the mouth'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-lAuX_I_zATA/Tlp7m5TkktI/AAAAAAAAHxk/UNQm0u_Lfnk/s72-c/horse-mouth2.jpg' height='72' width='72'/><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-4157487675751756126</id><published>2011-08-18T08:02:00.000-07:00</published><updated>2011-08-18T08:02:59.523-07:00</updated><title type='text'>Raycasting using AABB (Axis Aligned Bounding Volume) trees</title><content type='html'>&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-JjU7bjt4eQs/Tk0nOmrM5TI/AAAAAAAAHv8/ndmXfsxOkqg/s1600/winston+036.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="298" src="http://3.bp.blogspot.com/-JjU7bjt4eQs/Tk0nOmrM5TI/AAAAAAAAHv8/ndmXfsxOkqg/s400/winston+036.JPG" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Note: This photograph has nothing to do with this post; I just love showing off my new puppy Winston!&lt;/td&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Today I am releasing an arguably somewhat useful code snippet which can preform high-speed raycasting against an arbitrary triangle mesh.&amp;nbsp; Now, this isn't particularly unique.&amp;nbsp; There are many libraries on the internet for doing this; however this may be the only one presented as an actual 'code snippet'; meaning just a single header file and a single relatively modestly sized CPP implementation.&lt;br /&gt;&lt;br /&gt;If you need a robust general purpose raycasting and collision system I strongly recommend you use &lt;a href="http://www.codercorner.com/Opcode.htm"&gt;OPCODE &lt;/a&gt;written by my friend &lt;a href="http://www.codercorner.com/Pierre.htm"&gt;Pierre Terdiman&lt;/a&gt;.&amp;nbsp; OpCode is a phenomenal library that is extremely high performance.&amp;nbsp; You can also use the PhysX SDK from NVIDIA; which has a version of OPCODE internally which is also very high performance as well.&lt;br /&gt;&lt;br /&gt;However, OPCODE does a whole lot more than just simple raycasting against a triangle mesh; it has a lot of other features and is distributed as about 100 source files comprising tens of thousands of lines of code.&amp;nbsp; Again, this isn't an issue if you are working on a large project and want to add the library in.&lt;br /&gt;&lt;br /&gt;All that said, sometimes you are working on a small utility program or tool and you just need a quick and dirty way to raycast against a triangle mesh to speed up an algorithm.&amp;nbsp; In this case, you might find my implementation useful since you only need to add two small source files to your project.&lt;br /&gt;&lt;br /&gt;This code snippet might also serve as a nice educational tool for students trying to understand how to build and use an &lt;a href="http://www.cgal.org/Manual/3.5/doc_html/cgal_manual/AABB_tree/Chapter_main.html"&gt;axis-aligned-bounding-volume AABB tree.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can download the source code from this Google Code project page.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/raycastmesh/"&gt;RaycastMesh&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The project includes a sample application which will load a 3d mesh, perform a million raycast operations, and save out a PNG image file showing the results.&lt;br /&gt;&lt;br /&gt;However, to include it into your own project you need only the file 'RaycastMesh.h' and 'RaycastMesh.cpp'&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-4157487675751756126?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/raycastmesh/' title='Raycasting using AABB (Axis Aligned Bounding Volume) trees'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/4157487675751756126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=4157487675751756126' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/4157487675751756126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/4157487675751756126'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2011/08/raycasting-using-aabb-axis-aligned.html' title='Raycasting using AABB (Axis Aligned Bounding Volume) trees'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-JjU7bjt4eQs/Tk0nOmrM5TI/AAAAAAAAHv8/ndmXfsxOkqg/s72-c/winston+036.JPG' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-7286540007422327456</id><published>2011-07-11T14:27:00.000-07:00</published><updated>2011-07-11T14:27:28.380-07:00</updated><title type='text'>Revision to TestHACD</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-5x52NiVbnNo/ThtovIXzEcI/AAAAAAAAHss/9oSU8xqDbLU/s1600/connectivity.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="326" src="http://3.bp.blogspot.com/-5x52NiVbnNo/ThtovIXzEcI/AAAAAAAAHss/9oSU8xqDbLU/s400/connectivity.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;After making my post last week Khaled Mamou has made some bug fixes to his HACD implementation that takes extended mesh connectivity into account.&amp;nbsp; In the previous version, if you ran convex decomposition on a single input mesh that was actually comprised of say 10 separate unique sub-meshes (I like to call them 'mesh islands') then it would always produce a minimum of 10 convex hulls.&lt;br /&gt;&lt;br /&gt;Khaled fixed this by adding a new option called 'connectivity distance' which will merge mesh islands if they touch within this distance.&lt;br /&gt;&lt;br /&gt;I integrated Khaled's changes into my depot as well, and also removed my hack solution which performed hull merging to get around this previous problem.&lt;br /&gt;&lt;br /&gt;Right now my code and Khaled's are in sync, but my code drop is significantly refactored since I made it optional to build and run it either with or without the standard template library.&amp;nbsp; Perhaps we can combine our efforts sometime in the future but, for now, I will just continue to manually integrate changes.&lt;br /&gt;&lt;br /&gt;My current check-in adds support for my MeshImporter plugins which can import a wide variety of graphics file formats.&amp;nbsp; I will have a new MeshImporter plugin that will support COLLADA soon. This is a windows only feature; for non-windows developers there is an option to just compile in Wavefront OBJ support.&lt;br /&gt;&lt;br /&gt;Also, my current code drop has the beginnings of the automatic skeleton generation code.&amp;nbsp; As I find time this week, I will try to complete it.&amp;nbsp; This code will take an arbitrary triangle mesh, perform HACD on it, and then infer a skeleton at the points wherever two convex hulls touch each other.&amp;nbsp; As a final option it can auto-generate a skinned mesh from the original non-skinned artwork.&amp;nbsp; This will allow you to automatically create a ragdoll or psuedo-softbody from any arbitrary mesh.&lt;br /&gt;&lt;br /&gt;Here is the link to my depot on Google Code.&amp;nbsp; &lt;a href="http://code.google.com/p/testhacd/"&gt;TestHACD&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here is the link to Khaled Mamou's official copy of &lt;a href="http://sourceforge.net/projects/hacd/"&gt;HACD &lt;/a&gt;on SourceForge.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-7286540007422327456?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/testhacd/' title='Revision to TestHACD'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/7286540007422327456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=7286540007422327456' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/7286540007422327456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/7286540007422327456'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2011/07/revision-to-testhacd.html' title='Revision to TestHACD'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-5x52NiVbnNo/ThtovIXzEcI/AAAAAAAAHss/9oSU8xqDbLU/s72-c/connectivity.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-2693132246065632408</id><published>2011-07-07T16:57:00.000-07:00</published><updated>2011-07-08T07:58:29.927-07:00</updated><title type='text'>HACD : Hierarchical Approximate Convex Decomposition by Khaled Mamou Sample Application</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-5Fg_QLwLZXI/ThZFypPcHLI/AAAAAAAAHso/RfUY4RcDuMQ/s1600/winston%2B035.JPG" imageanchor="1"&gt;&lt;img border="0" height="299" src="http://3.bp.blogspot.com/-5Fg_QLwLZXI/ThZFypPcHLI/AAAAAAAAHso/RfUY4RcDuMQ/s400/winston%2B035.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I have just created and made available&lt;a href="http://code.google.com/p/testhacd/"&gt; a test application&lt;/a&gt; for people to use/experiment with Khaled Mamou's excellent HACD system.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/testhacd/"&gt;TestHACD on Google Code&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Due to requirements that I have at my job, I had to refactor the code so that it did not use any of the standard template library (STL) and 100% of all memory allocations had to be trapped by a user provided allocator. (i.e. no global new/delete, malloc, free). &lt;br /&gt;&lt;br /&gt;One of the more challenging things to factor out regarding the STL was the use of the STL set and map containers.&amp;nbsp; To accomplish this what I did was refactor a copy of the EASTL (written by Paul Pedriana).&amp;nbsp; Even though Paul's EASTL is a dramatically smaller code base than the full STL implementation, I went a step further and refactored his code so that I extracted *only* the STL map/set containers and nothing else.&amp;nbsp; I then put this refactored code into just three small source files where all memory allocations and data types could be trapped and revectored.&lt;br /&gt;&lt;br /&gt;There is a single header file in the provided project 'PxSimpleTypes.h'.&amp;nbsp; You can modify the data types and memory allocation macros in this one header file to make the source conform to the coding standard of your own game engine, or at least it provides a single easy location to do some global find/replace on the source to make it conform to your internal standards.&lt;br /&gt;&lt;br /&gt;Khaled's algorithm produces absolutely amazing results much better than my version ever did.&amp;nbsp; However, one thing I have yet to be able to get his to do is produce just one our two hulls.&lt;br /&gt;&lt;br /&gt;With the provided sample mesh no matter what I set the concavity threshold to, no matter how high, I still get 14 convex hulls.&amp;nbsp; I don't know if this is a limitation of his algorithm or I am not exposing all of the correct parameters at this time.&lt;br /&gt;&lt;br /&gt;If you wish to make improvements to this code, please let me know and I will add you to the Google Code project so you can make changes.&amp;nbsp; Also, sometime in the next week, I am going to revise the code to auto-generate a skeletal deformed mesh from the HACD output.&amp;nbsp; I will add this to the TestHACD open source project.&lt;br /&gt;&lt;br /&gt;Be aware that Khaled's algorithm can be extremely CPU intensive.&amp;nbsp; With triangle meshes with very large vertex counts; it could possibly take an extremely lengthy period of time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-2693132246065632408?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/testhacd/' title='HACD : Hierarchical Approximate Convex Decomposition by Khaled Mamou Sample Application'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/2693132246065632408/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=2693132246065632408' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2693132246065632408'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2693132246065632408'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2011/07/hacd-hierarchical-approximate-convex.html' title='HACD : Hierarchical Approximate Convex Decomposition by Khaled Mamou Sample Application'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-5Fg_QLwLZXI/ThZFypPcHLI/AAAAAAAAHso/RfUY4RcDuMQ/s72-c/winston%2B035.JPG' height='72' width='72'/><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-6064875675585905088</id><published>2011-06-04T06:36:00.000-07:00</published><updated>2011-06-04T06:36:38.196-07:00</updated><title type='text'>Overly Optimistic?</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-NNpMOPU7RE4/Teo0hY46MlI/AAAAAAAAHl4/otG_MV3dgPE/s1600/fat-people-persistence-cook.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://1.bp.blogspot.com/-NNpMOPU7RE4/Teo0hY46MlI/AAAAAAAAHl4/otG_MV3dgPE/s400/fat-people-persistence-cook.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I just had someone post a comment on the blog about my overly optimistic view of my new project.  I figured I would post my answers so everyone else interested could read them as well.&lt;br /&gt;&lt;br /&gt;&gt;&gt;overly optimistic/ambitious?&lt;br /&gt;&lt;br /&gt;That's not an unfair assessment.&amp;nbsp; However, I do have confidence in a few things.&amp;nbsp; I'm confident that I can do this project; based on the fact that I have successfully completed similar projects in the past, more than once.&lt;br /&gt;&lt;br /&gt;I am also confident that I am managing technical risk.&lt;br /&gt;&lt;br /&gt;For example, one of my first requirements is not to get even any game play working.&amp;nbsp; My first requirement is to get a server written that can manage 1,000 simultaneous connections and to test it with bot scripts which actually create 1,000 connections and move characters around the world.&lt;br /&gt;&lt;br /&gt;The 'M' in MMO stands for 'massive' and if I can't achieve that, then nothing about the game client really matters.&lt;br /&gt;&lt;br /&gt;The key to success, in my view, is to provide a unique truly massive gaming experience; the kind you could only ever get, to date, from 'Planetside' and do better.&amp;nbsp; Having been the lead software engineer on 'Planetside' I would like to think I know a little bit about this.&lt;br /&gt;&lt;br /&gt;&amp;gt;&amp;gt;have you already prioritized a list of features so that you know what to drop when you don't meet deadlines?&lt;br /&gt;&lt;br /&gt;Yes.&amp;nbsp; I'm using Agile/Scrum methodology and Rally to track everything.&lt;br /&gt;&lt;br /&gt;&amp;gt;&amp;gt;(and have designed play tests to know that these features aren't make-or-break?)&lt;br /&gt;&lt;br /&gt;Well, we aren't doing the project that way.&amp;nbsp; This project will be in a continuous state of open beta from the day we have enough server infrastructure in place and two people can walk around the game world.&amp;nbsp; The game will never officially 'ship' in that sense; but rather features will continuously be added, and game design refined through play test over time.&lt;br /&gt;&lt;br /&gt;This is the only way any truly successful multiplayer game gets developed.&amp;nbsp; If you do not always have a playable game, during the entire development process, you are taking an absurd risk in my opinion.&lt;br /&gt;&lt;br /&gt;And, while we will never officially 'ship' the game, we will officially start charging people money for beta testing.&lt;br /&gt;&lt;br /&gt;However, even then we have a lot of flexibility.&amp;nbsp; One of the key things to test is the monetization of the game, and what works best.&amp;nbsp; So monetization will be play tested and balanced just like everything else.&lt;br /&gt;&lt;br /&gt;My design is that, from the stand point of the game mechanics, you will never play the game for 'free'.&amp;nbsp; What will be free are credits to play the game, which I will hand out with abandon to anyone who is willing to help us test and tune the development process.&lt;br /&gt;&lt;br /&gt;Once the game reaches a level that it is truly fun to play, and I feel worth charging money for, at that point I will just stop giving away so many free credits.&lt;br /&gt;&lt;br /&gt;For example, let's say you want to beta test.&amp;nbsp; Well, I can give you a $100 worth of credits to play the game (enough credits to play the game a ridiculous number of hours for five months).&lt;br /&gt;&lt;br /&gt;Once those credits run out, if that guy is still in beta test, he is going to want some more credits to keep playing the game.&lt;br /&gt;&lt;br /&gt;If I haven't created a game that is enough fun to accomplish this, then I will have failed.&lt;br /&gt;&lt;br /&gt;However, this game is starting with a known, proven, and completely addictive game design.&amp;nbsp; So, my confidence level is fairly high that I can find a decent sized group of people who will enjoy playing it and be willing to pay a modest amount of money for the privilege. I'm not talking about charging them some absurd amount of money in subscription fees, or annoying the shit out of them with micro-transactions and/or advertising.&amp;nbsp; My initial plan is simply to charge very modest some of money per time played.&amp;nbsp; Something roughly on the order of 25 cents for half an hour.&amp;nbsp; But, this too, is all subject to change, refinement, and tuning as testing plays out.&lt;br /&gt;&lt;br /&gt;This game is going to provide a unique gaming experience you simply cannot get anywhere else in any other form.&lt;br /&gt;&lt;br /&gt;&amp;gt;&amp;gt;anyway, good luck with it all! Keen to see your demo in 2 weeks&lt;br /&gt;&lt;br /&gt;Thanks, looking forward to getting it out!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-6064875675585905088?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/6064875675585905088/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=6064875675585905088' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/6064875675585905088'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/6064875675585905088'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2011/06/overly-optimistic.html' title='Overly Optimistic?'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-NNpMOPU7RE4/Teo0hY46MlI/AAAAAAAAHl4/otG_MV3dgPE/s72-c/fat-people-persistence-cook.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-1154751030147991078</id><published>2011-06-03T09:25:00.000-07:00</published><updated>2011-06-03T09:25:42.967-07:00</updated><title type='text'>Progress update</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://2.bp.blogspot.com/-ONTMv21RhyY/TekJVLlkfUI/AAAAAAAAHlw/uzKTBbprSSM/s1600/me.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-ONTMv21RhyY/TekJVLlkfUI/AAAAAAAAHlw/uzKTBbprSSM/s1600/me.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I have made some big decisions to move this project forward in the past 24 hours; and these decisions involved committing thousands of dollars out of my own savings to get things off the ground.&lt;br /&gt;&lt;br /&gt;First, I have formed a limited liability corporation, under the name 'Duatiu LLC', which will have 10,000 shares of stock to distribute to partners.&lt;br /&gt;&lt;br /&gt;Second, I filed a trademark application on the name 'Duatiu'.&amp;nbsp; I expect no difficulties since the name is a coined term and doesn't show up anywhere on any search engines.&lt;br /&gt;&lt;br /&gt;Third, I have come to an agreement with partner Shawn Presser to work on Duatiu *full time* for the indefinite future.&amp;nbsp; Shawn is being reimbursed for his time spent on this project as a combination of shares of stock and a modest amount of cash to help defray his own personal expenses.&lt;br /&gt;&lt;br /&gt;This is a pretty big deal; having a talented software engineer able to work on the project full time should go a long way towards pushing the game to the next level.&lt;br /&gt;&lt;br /&gt;Our current ball park milestones are as follows:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Within Two Weeks&lt;/b&gt; : A downloadable demo of the Duatiu game world.&amp;nbsp; You will be able to fly a free camera and walk an avatar around the game environment.&amp;nbsp; The visual production values will be close to the final product.&amp;nbsp; Using precomputed radiosity, nice diffuse textures, and a high resolution detail texture, we expect the game environment itself to be very visually stunning.&amp;nbsp; The game engine is being written exclusively in C++ for OpenGL.&amp;nbsp; While it will initially run on Windows; it may at a future time run on a wide array of tablet operating systems.&amp;nbsp; (Perhaps of interest to the programmers who follow this blog, I will be releasing my radiosity lightmapping tool completely open source at the same time.)&lt;/li&gt;&lt;li&gt;&lt;b&gt;Within Four to Six Weeks&lt;/b&gt; : Be able to connect to a server, hosted on Amazon.com, and walk around the game environment and see avatars representing other playrs.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Within Three Months&lt;/b&gt; : Be able to play a simple basic game involving calling in supplies, operating a shield, and shooting human opponents; all in a multiplayer environment.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Within Six Months&lt;/b&gt; : Functional AI agents running on the server; more of the actual game play implemented.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;These are just back of the napkin estimates, but it does give you a general ideal of the scope and time frame we are thinking about.&amp;nbsp; I'm extremely excited that Shawn has committed to working full time on this project.&amp;nbsp; I expect good things to come from this soon!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-1154751030147991078?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/1154751030147991078/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=1154751030147991078' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1154751030147991078'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1154751030147991078'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2011/06/progress-update.html' title='Progress update'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-ONTMv21RhyY/TekJVLlkfUI/AAAAAAAAHlw/uzKTBbprSSM/s72-c/me.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-931469183547988171</id><published>2011-06-02T09:04:00.001-07:00</published><updated>2011-06-02T09:19:40.675-07:00</updated><title type='text'>My new project 'Duatiu' is actually getting some traction after just 24 hours of announcing it!</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-mHsJpHiyQU0/TeezKQPZi6I/AAAAAAAAHls/eJJuyjxpYps/s1600/teamwork-it-must-be-stopped-demotivational-poster-1256340897.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="346" src="http://3.bp.blogspot.com/-mHsJpHiyQU0/TeezKQPZi6I/AAAAAAAAHls/eJJuyjxpYps/s400/teamwork-it-must-be-stopped-demotivational-poster-1256340897.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Well, I have already received quite a bit of positive feedback in the past 24 hours about this project.&amp;nbsp; First, a number of my friends in the industry have promised to help me out and that has been amazing!&lt;br /&gt;&lt;br /&gt;So far I have commitments of time from:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://shawnpresser.blogspot.com/"&gt;Shawn Presse&lt;/a&gt;r : Who is writing the core graphics engine and has already  been working on the project for several months.&amp;nbsp; Shawn's contributions  to this project have already been amazing.&amp;nbsp; We are currently working  towards our first milestone to provide a demo that will allow  anyone to run a character around one of our game world environments  sometime in the next couple of weeks. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://code4software.com/GameDev.aspx"&gt;Jared Freedman&lt;/a&gt;, An excellent game designer, developer, long time friend, and all around good guy.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.z425.com/"&gt;Billy Zelsnack&lt;/a&gt; : Billy is a well known figure in the game industry and a long time friend.&amp;nbsp; He has volunteered to help with the game project when he can. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cbloom.com/"&gt;Charles Bloom&lt;/a&gt; : It helps to have good friends in the game industry and Charles, even though he is one of the top guys in the world he still took the time yesterday just to whip up a little bit of code I needed to solve a problem.&amp;nbsp; I see shares of stock in Charles's future.&amp;nbsp; Plus, he's a fellow Porsche fan so we have that in common.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.thegleam.com/"&gt;John Miles&lt;/a&gt; :&amp;nbsp; What has John Miles done on this project?&amp;nbsp; Nothing.&amp;nbsp; Does John Miles even know that this project exists?&amp;nbsp; Probably not.&amp;nbsp; Have I even asked John Miles if he will work on this project?&amp;nbsp; No I haven't.&amp;nbsp; But, as a life long friend, I'm sure he will help me out when I need it.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://docs.google.com/viewer?a=v&amp;amp;pid=gmail&amp;amp;attid=0.1&amp;amp;thid=13050c525db31d1a&amp;amp;mt=application/pdf&amp;amp;url=https://mail.google.com/mail/?ui%3D2%26ik%3D68363f08f6%26view%3Datt%26th%3D13050c525db31d1a%26attid%3D0.1%26disp%3Dsafe%26realattid%3Df_gofswgf60%26zw&amp;amp;sig=AHIEtbTB2uJnagIOlRjyFvarfjgTdGcC1A"&gt;Wajih-Halim&lt;/a&gt; : A recent college graduate in computer science who wishes to help with graphics special effects on the game.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.linkedin.com/in/benhesketh"&gt;Ben Hesketh&lt;/a&gt; : Runs his own successful game company and contacted me from this website because he thinks the project sounds interesting.&amp;nbsp; Ben has volunteered to contribute on the server code.&amp;nbsp; The website for Ben's company, &lt;a href="http://www.compassengine.com/"&gt;Compass Engine&lt;/a&gt;, can be found here.&amp;nbsp; And a link to his recent game '&lt;a href="http://itunes.apple.com/ca/app/bounty-island/id416453791?mt=8&amp;amp;ign-mpt=uo%3D4"&gt;Bounty Island&lt;/a&gt;' can be found here.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.linkedin.com/in/robertsitton"&gt;Robert Sitton&lt;/a&gt; : Robert is a long time game industry veteran and was one of my key sidekicks when developing the game 'Planetside' for Sony Online Entertainment.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.myspace.com/psybz"&gt;Joe Bizz&lt;/a&gt; : Musician and sound engineer and fellow UFO enthusiast.&amp;nbsp; So how that networking shit works?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.radgametools.com/"&gt;RAD Game Tool&lt;/a&gt;s : The guys at Rad Game Tools are long time friends of mine, Jeff, Mitch, David, Brian, Sean, and others.&amp;nbsp; They have always been extremely helpful in supporting me and my projects and it looks like I may be able use their latest product 'Iggy' to accelerate the development process for this game.&amp;nbsp; '&lt;a href="http://www.radgametools.com/iggy.htm"&gt;Iggy&lt;/a&gt;' is an amazing product written by the the no less amazing &lt;a href="http://nothings.org/"&gt;Sean Patrick Barrett&lt;/a&gt; (one of the Gods of the open source community).&amp;nbsp; '&lt;a href="http://www.radgametools.com/iggy.htm"&gt;Iggy&lt;/a&gt;' is an embedded Adobe flash engine that virtually eliminates the need to do any custom user interface programming.&amp;nbsp; The entire user interface for a game becomes a series of Flash/ActionScript/FLEX data assets.&amp;nbsp; This should greatly accelerate the development of the user interface for this game.&amp;nbsp; Of course, that means that now, instead of looking for a GUI programmer, I need an expert who knows how to use these tools; but that seems like a much simpler hurdle to leap.&lt;br /&gt;&lt;br /&gt;This is a really good start to the virtual team, but I still need some more artists to join the project.&amp;nbsp; Hopefully when people see the caliber of people involved they will realize they are missing the boat if they don't hop on soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-931469183547988171?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/931469183547988171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=931469183547988171' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/931469183547988171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/931469183547988171'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2011/06/my-new-project-duatiu-is-actually.html' title='My new project &apos;Duatiu&apos; is actually getting some traction after just 24 hours of announcing it!'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-mHsJpHiyQU0/TeezKQPZi6I/AAAAAAAAHls/eJJuyjxpYps/s72-c/teamwork-it-must-be-stopped-demotivational-poster-1256340897.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-1007432576491704090</id><published>2011-05-31T16:20:00.000-07:00</published><updated>2011-05-31T16:20:05.627-07:00</updated><title type='text'>Duatiu ; A Massively Multiplayer Online First Person Shooter written by.....you?</title><content type='html'>&lt;iframe width="425" height="349" src="http://www.youtube.com/embed/fssGiDlWwlk" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;For those who follow this blog, please check out the &lt;a href="http://duatiu.blogspot.com/"&gt;website and postings about a new project&lt;/a&gt; I'm trying to get off the ground.&amp;nbsp; Feedback, but more importantly, partners wanted.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-1007432576491704090?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://duatiu.blogspot.com/2011/05/job-openings-who-do-you-need-to-work.html' title='Duatiu ; A Massively Multiplayer Online First Person Shooter written by.....you?'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/1007432576491704090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=1007432576491704090' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1007432576491704090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1007432576491704090'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2011/05/duatiu-massively-multiplayer-online.html' title='Duatiu ; A Massively Multiplayer Online First Person Shooter written by.....you?'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/fssGiDlWwlk/default.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-4464619868292187274</id><published>2011-05-20T13:17:00.000-07:00</published><updated>2011-05-20T13:26:42.130-07:00</updated><title type='text'>HACD : Hierarchical Approximate Convex Decomposition by Khaled Mamou</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-ID52QCyJHnc/TdbIh8HgIPI/AAAAAAAAHkQ/SgXgtCvvxoQ/s1600/bowl.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="212" src="http://4.bp.blogspot.com/-ID52QCyJHnc/TdbIh8HgIPI/AAAAAAAAHkQ/SgXgtCvvxoQ/s400/bowl.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-qALWgyt7Py4/TdbIiHFhnGI/AAAAAAAAHkU/LP2irklY85E/s1600/bunny.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="226" src="http://2.bp.blogspot.com/-qALWgyt7Py4/TdbIiHFhnGI/AAAAAAAAHkU/LP2irklY85E/s400/bunny.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-H2YWVauHrd0/TdbIiopScmI/AAAAAAAAHkY/nOTF_dwpJJE/s1600/cmp_bunny.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="165" src="http://3.bp.blogspot.com/-H2YWVauHrd0/TdbIiopScmI/AAAAAAAAHkY/nOTF_dwpJJE/s400/cmp_bunny.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Many people come to this weblog because they are searching on terms for 'Convex Decomposition'.&amp;nbsp; This blog post is to announce that there is a much, much, better open source implementation than the one I did.&amp;nbsp; I suppose I can take some tiny credit as my work appears to have inspired the authors of the new algorithm but that's not really saying much.&amp;nbsp; All credit where credit is due and the open source implementation released by Khaled Mamou is vastly superior to the brute force approach that mine took.&amp;nbsp; His is much more elegant and also solves a lot of extremely hard problems; such as objects with holes in them (something my algorithm could not deal with).&amp;nbsp; His also does not suffer with the problem mine had with excessive recursion depths producing hollow interiors.&lt;br /&gt;&lt;br /&gt;You can find the paper for this algorithm at this location:&lt;br /&gt;&lt;br /&gt;&lt;a href="ftp://ftp.elet.polimi.it/users/Stefano.Tubaro/ICIP_USB_Proceedings_v2/pdfs/0003501.pdf"&gt;ftp://ftp.elet.polimi.it/users/Stefano.Tubaro/ICIP_USB_Proceedings_v2/pdfs/0003501.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You can download the source to HACD from this location on SourceForge&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sourceforge.net/projects/hacd/"&gt;http://sourceforge.net/projects/hacd/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;With this announcement I will no longer be supporting my legacy ConvexDecomposition code in any way.&amp;nbsp; I am switching to using HADC in all of my projects.&amp;nbsp; I recommend you do the same.&lt;br /&gt;&lt;br /&gt;Congratulations to Khaled and Faouzi who have done a fantastic job on an important problem.&lt;br /&gt;&lt;br /&gt;One thing I will volunteer to the community is that sometime soon, I will create an open source tool using HACD that will auto-generate skeletal deformed meshes.&lt;br /&gt;&lt;br /&gt;If you simply look at these various screenshots you will notice that the convex decomposition naturally produces a logical skeleton for an arbitrary piece of geometry.&amp;nbsp; Obviously, that skeleton isn't perfect compared to what an artist would create but it is certainly a useful approximate skeleton.&lt;br /&gt;&lt;br /&gt;From previous work I have done on the 'create dynamics' project, I know that you can not only synthesize a skeleton but you can also auto-generate skinned bone weightings.&amp;nbsp; If you then create physical collision shapes which are constrained at these joint locations you can get an extremely convincing looking softbody object; with accurate collisions, in a very CPU cheap fashion.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-CeHFbsnudlM/TdbIjF5eF-I/AAAAAAAAHkc/d54x7MMEG-U/s1600/cmp_dino.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="168" src="http://4.bp.blogspot.com/-CeHFbsnudlM/TdbIjF5eF-I/AAAAAAAAHkc/d54x7MMEG-U/s400/cmp_dino.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-VgZWFTcAqsM/TdbIkaJoGAI/AAAAAAAAHkg/MK_fo1llWpw/s1600/cmp_hand.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="216" src="http://3.bp.blogspot.com/-VgZWFTcAqsM/TdbIkaJoGAI/AAAAAAAAHkg/MK_fo1llWpw/s400/cmp_hand.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-US-N-XBBUpM/TdbIk7dk9HI/AAAAAAAAHkk/v-Ve_a36rsA/s1600/cmp_octopus.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="132" src="http://1.bp.blogspot.com/-US-N-XBBUpM/TdbIk7dk9HI/AAAAAAAAHkk/v-Ve_a36rsA/s400/cmp_octopus.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-mfnIykEp1fY/TdbIlavttmI/AAAAAAAAHko/ErG9xZypxfI/s1600/creature.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="237" src="http://4.bp.blogspot.com/-mfnIykEp1fY/TdbIlavttmI/AAAAAAAAHko/ErG9xZypxfI/s400/creature.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-CCB0j8Kj1Vo/TdbIlm1B7bI/AAAAAAAAHks/2HnZ-bdluE0/s1600/dilo.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="93" src="http://1.bp.blogspot.com/-CCB0j8Kj1Vo/TdbIlm1B7bI/AAAAAAAAHks/2HnZ-bdluE0/s400/dilo.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-G7ZCdSnI-oI/TdbIlw-LsAI/AAAAAAAAHkw/zOKl3dZQoRQ/s1600/dino.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="237" src="http://1.bp.blogspot.com/-G7ZCdSnI-oI/TdbIlw-LsAI/AAAAAAAAHkw/zOKl3dZQoRQ/s400/dino.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-sYGO43dcRbY/TdbImrghbVI/AAAAAAAAHk0/Gyomj6UgZwU/s1600/egea.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="203" src="http://4.bp.blogspot.com/-sYGO43dcRbY/TdbImrghbVI/AAAAAAAAHk0/Gyomj6UgZwU/s400/egea.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Ca73ud3RvNE/TdbInFbKcUI/AAAAAAAAHk4/uKGpY76yMRE/s1600/elk.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="220" src="http://4.bp.blogspot.com/-Ca73ud3RvNE/TdbInFbKcUI/AAAAAAAAHk4/uKGpY76yMRE/s400/elk.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-PnHbn9wyeEg/TdbInuyc9SI/AAAAAAAAHk8/gq_o1WLJXFY/s1600/extraPoints.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-55bJbLUAows/TdbIoDsE6qI/AAAAAAAAHlA/TZB0F0TEbSI/s1600/feline.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="218" src="http://3.bp.blogspot.com/-55bJbLUAows/TdbIoDsE6qI/AAAAAAAAHlA/TZB0F0TEbSI/s400/feline.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-N0sRdP_xU5I/TdbIoSHF_nI/AAAAAAAAHlE/DPDyg2IyLew/s1600/fish.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="208" src="http://2.bp.blogspot.com/-N0sRdP_xU5I/TdbIoSHF_nI/AAAAAAAAHlE/DPDyg2IyLew/s400/fish.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-FE4w69PU26c/TdbIo-Ckj8I/AAAAAAAAHlI/J7_73M4mPG0/s1600/foot.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="95" src="http://3.bp.blogspot.com/-FE4w69PU26c/TdbIo-Ckj8I/AAAAAAAAHlI/J7_73M4mPG0/s400/foot.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-iHb7XpS81QQ/TdbIpFxV7sI/AAAAAAAAHlM/5W6uN_kwPWY/s1600/hand.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="295" src="http://4.bp.blogspot.com/-iHb7XpS81QQ/TdbIpFxV7sI/AAAAAAAAHlM/5W6uN_kwPWY/s400/hand.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-HS48rn8iUlk/TdbIpkwq88I/AAAAAAAAHlQ/xPStdD1D_Dc/s1600/Homer.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="331" src="http://4.bp.blogspot.com/-HS48rn8iUlk/TdbIpkwq88I/AAAAAAAAHlQ/xPStdD1D_Dc/s400/Homer.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-M7XsOHCaxkg/TdbIp4Vf-eI/AAAAAAAAHlU/zUCrAd6SpAU/s1600/horse.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="180" src="http://1.bp.blogspot.com/-M7XsOHCaxkg/TdbIp4Vf-eI/AAAAAAAAHlU/zUCrAd6SpAU/s400/horse.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-RjbVxqYNY18/TdbIqZr05II/AAAAAAAAHlY/JN43uLT9j2U/s1600/octopus.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="138" src="http://3.bp.blogspot.com/-RjbVxqYNY18/TdbIqZr05II/AAAAAAAAHlY/JN43uLT9j2U/s400/octopus.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-TCUTat9lCjU/TdbIqnddNII/AAAAAAAAHlc/qH4bRCkCvqg/s1600/pig.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="160" src="http://1.bp.blogspot.com/-TCUTat9lCjU/TdbIqnddNII/AAAAAAAAHlc/qH4bRCkCvqg/s400/pig.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-5pDJOQNma6M/TdbIrEKAmLI/AAAAAAAAHlg/moaY5fnNl3Y/s1600/polygirl.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/-5pDJOQNma6M/TdbIrEKAmLI/AAAAAAAAHlg/moaY5fnNl3Y/s400/polygirl.jpg" width="365" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-al-_1vCO6DE/TdbIrhyjoLI/AAAAAAAAHlk/WolkTRzfQ3U/s1600/rabbit.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://2.bp.blogspot.com/-al-_1vCO6DE/TdbIrhyjoLI/AAAAAAAAHlk/WolkTRzfQ3U/s400/rabbit.jpg" width="367" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-4464619868292187274?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://sourceforge.net/projects/hacd/' title='HACD : Hierarchical Approximate Convex Decomposition by Khaled Mamou'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/4464619868292187274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=4464619868292187274' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/4464619868292187274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/4464619868292187274'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2011/05/hacd-hierarchical-approximate-convex.html' title='HACD : Hierarchical Approximate Convex Decomposition by Khaled Mamou'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-ID52QCyJHnc/TdbIh8HgIPI/AAAAAAAAHkQ/SgXgtCvvxoQ/s72-c/bowl.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-8016837549612953083</id><published>2010-12-02T10:04:00.000-08:00</published><updated>2010-12-02T10:27:17.587-08:00</updated><title type='text'>K-Means Clustering Algorithm</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_PtTKwwh_xBc/TPfa6pEPCJI/AAAAAAAAHeo/maBNohJ7Le4/s1600/kmeans7.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_PtTKwwh_xBc/TPfa6pEPCJI/AAAAAAAAHeo/maBNohJ7Le4/s400/kmeans7.jpg" width="382" /&gt;&amp;nbsp;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;I haven't uploaded a new code snippet in quite a while, not because I haven't been coding, I've just been coding in a certain unnamed behemoth game engine that doesn't lend itself to writing anything in 'snippet' form.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;However, I am working on a new project for a short period of time and yesterday I needed to solve a problem that, apparently, lots of people have solved before.&amp;nbsp;&amp;nbsp; I have a large set of data points (in this case representing objects at different scales) and I needed to reduce it to a smaller subset of the (N) number of most significant sizes.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;This is a common problem, and many developers have seen it when trying to reduce a color-space.&amp;nbsp; (For example reducing an image with say 16k colors to only 256 colors used to be a common thing people needed to do).&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;One of the more elegant solutions to this problem is by building an octree; at least one version of this algorithm is called '&lt;a href="http://www.ece.mcmaster.ca/%7Exwu/"&gt;Wu Quantization&lt;/a&gt;'.&amp;nbsp; This was popularly presented in &lt;a href="http://books.google.com/books?id=fvA7zLEFWZgC&amp;amp;pg=PA287&amp;amp;lpg=PA287&amp;amp;dq=octree+color+quantization+graphics+gems+Andrew+Glassner&amp;amp;source=bl&amp;amp;ots=7LeDq2kEUk&amp;amp;sig=W4-fA92eSKcBobz8ZP5dcuaPMrI&amp;amp;hl=en&amp;amp;ei=S9z3TPe3FsOUswb73vXZCA&amp;amp;sa=X&amp;amp;oi=book_result&amp;amp;ct=result&amp;amp;resnum=1&amp;amp;ved=0CBMQ6AEwAA#v=onepage&amp;amp;q=octree%20color%20quantization%20graphics%20gems%20Andrew%20Glassner&amp;amp;f=false"&gt;Graphics Gems&lt;/a&gt;.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;What I needed yesterday was something very quick and dirty and, that turned out to be the K-means clustering algorithm.&amp;nbsp; You can read about it here on &lt;a href="http://en.wikipedia.org/wiki/K-means_clustering"&gt;Wikipedia &lt;/a&gt;and here is another link comparing it to a &lt;a href="http://www.optimaldesign.com/ArrayMiner/AMAlgorithms.html"&gt;different algorithm&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The algorithm itself is very straightforward.&lt;br /&gt;&lt;br /&gt;Let's say you have 100 input data points, but you want to reduce them to say 10 clusters where the center of each cluster represents the mean of the surrounding points.&lt;br /&gt;&lt;br /&gt;Step #1 : You seed the 10 clusters with the 10 sample points taken from the input data.&lt;br /&gt;&lt;br /&gt;Step #2 : You set an temp array of counts to zero and temp points to zero for each cluster you are building.&lt;br /&gt;&lt;br /&gt;Step #3 : You iterate through each of the input data points.&amp;nbsp; For each point you figure out which of the current clusters it is closest to.&amp;nbsp; You then add that point to the new set of centroids and increment a counter.&lt;br /&gt;&lt;br /&gt;Step #4 : You accumulate a total distance error of each point from its nearest cluster.&lt;br /&gt;&lt;br /&gt;Step #5 : You compute the average center position for each of the centroids and assign them as your new clusters.&lt;br /&gt;&lt;br /&gt;Step #6 : You compute the difference between the distance error on this pass and the distance error on the previous pass.&amp;nbsp; If the difference in the error is less than a tolerance passed in, you are done.&amp;nbsp; If the error is still converging, then you go back to step #2 and continue the loop.&lt;br /&gt;&lt;br /&gt;My implementation also added the ability to prune the results.&amp;nbsp; Pruning is needed if all of the input points are at the same location, or there are fewer input points than clusters requested.&lt;br /&gt;&lt;br /&gt;Another reason to prune the output is in the following example.&amp;nbsp; Let's say you have 100 data points that you want to put into 10 clusters.&amp;nbsp; However, all of those data points are right next to each other.&lt;br /&gt;&lt;br /&gt;The standard K-means algorithm will still produce 10 clusters, since it is basically unit-less.&amp;nbsp; However, this implementation allows you to specify a tolerance threshold that says if two clusters are practically next to each other, simply merge them.&lt;br /&gt;&lt;br /&gt;The main reason I am posting this code snippet is because of the absolutely abhorrent code snippet I found on the internet.&lt;br /&gt;&lt;br /&gt;Click on this link to see the C implementation version that I found on the Internet.&amp;nbsp; Clear as mud right?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/kmeans.c"&gt; kmeans.c&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Oh yeah, I would like to also add this.&amp;nbsp; There is a link to a C++ implementation on the Wikipedia page.&amp;nbsp; I downloaded that link and it uses not only the STL but BOOST as well!&lt;br /&gt;&lt;br /&gt;Yikes.&amp;nbsp; Mine has a vanilla C style function interface, accepts pointers to 1d, 2d, 3d, or 4d arrays of data points as either a const float pointer or const double pointer and uses no STL, or BOOST, or any other fluffy nonsense.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now, here is the header file and C++ for the version that I wrote.&amp;nbsp; I hope you will agree it is a lot easier to understand and use.&amp;nbsp; As always, feedback welcome.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/kmeans.h"&gt;kmeans.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/kmeans.cpp"&gt;kmeans.cpp &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-8016837549612953083?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://en.wikipedia.org/wiki/K-means_clustering' title='K-Means Clustering Algorithm'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/8016837549612953083/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=8016837549612953083' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8016837549612953083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8016837549612953083'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2010/12/k-means-clustering-algorithm.html' title='K-Means Clustering Algorithm'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_PtTKwwh_xBc/TPfa6pEPCJI/AAAAAAAAHeo/maBNohJ7Le4/s72-c/kmeans7.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-8382041046455233618</id><published>2010-04-18T07:59:00.000-07:00</published><updated>2010-04-18T14:00:28.955-07:00</updated><title type='text'>Understanding a .MAP file</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_PtTKwwh_xBc/S8scZcC6f-I/AAAAAAAAG8c/nmBiX2odLBw/s1600/13+%281%29.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://1.bp.blogspot.com/_PtTKwwh_xBc/S8scZcC6f-I/AAAAAAAAG8c/nmBiX2odLBw/s400/13+%281%29.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;My friend Andy Finkenstadt helped me figure this out.&amp;nbsp; Apparently the contents of a .MAP file are *not* in sorted order.&amp;nbsp; I will write a follow-up to this post later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-8382041046455233618?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/with_framework.map' title='Understanding a .MAP file'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/8382041046455233618/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=8382041046455233618' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8382041046455233618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8382041046455233618'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2010/04/understanding-map-file.html' title='Understanding a .MAP file'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_PtTKwwh_xBc/S8scZcC6f-I/AAAAAAAAG8c/nmBiX2odLBw/s72-c/13+%281%29.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-8741899550813095001</id><published>2010-03-27T13:39:00.000-07:00</published><updated>2010-03-27T13:39:46.877-07:00</updated><title type='text'>Memory Tracking Utility</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_PtTKwwh_xBc/S65l4efXKgI/AAAAAAAAG8M/y4KWFsZNeL4/s1600/tumblr_kw8uwzRF7Z1qzr53co1_500.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_PtTKwwh_xBc/S65l4efXKgI/AAAAAAAAG8M/y4KWFsZNeL4/s400/tumblr_kw8uwzRF7Z1qzr53co1_500.jpg" width="277" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Today's code snippet is a very useful tool.&amp;nbsp; The default version is provided as a 32 bit windows DLL.&amp;nbsp; There is no reason the code couldn't be refactored to be used on other platforms, but that wasn't a requirement for my own personal use.&lt;br /&gt;&lt;br /&gt;This tool is used to detect and identify memory leaks when an application exits or, more commonly, used to simply identify where all of your memory allocations are coming from.&lt;br /&gt;&lt;br /&gt;What's nice about using this tool as a DLL, rather than source code, is that it doesn't directly affect any of your existing allocation code.&lt;br /&gt;&lt;br /&gt;This code does *not* trap memory allocations.&amp;nbsp; You must already be doing that yourself.&amp;nbsp; What it does is allow you to track and report on those allocations.&lt;br /&gt;&lt;br /&gt;Ideally your application would trap every single new/delete malloc/free performed.&amp;nbsp; This can be done in a variety of different ways, either by replacing the global memory allocator, or by inheriting a base allocator class.&lt;br /&gt;&lt;br /&gt;I strongly recommend that every class in your code base inherit a default allocator class.&amp;nbsp; Then, in every location where you used to do a 'new' operator, replace that with a macro expansion which calls an inherited new operator which accepts class name, file name, and line number.&lt;br /&gt;&lt;br /&gt;The value of the Memory Tracking report is only as good as the data you feed into it.&amp;nbsp; If you feed into it the class name, source code filename and line number for every allocation then the report will be able to give you some tremendous information identify when, how, and where, all of your memory allocations are occurring.&lt;br /&gt;&lt;br /&gt;One problem with tracking all memory allocations is with templates.&amp;nbsp; When you do a lot of template metaprogramming it becomes difficult to know where the source allocations are occurring.&amp;nbsp; Sometimes it is useful to add additional parameters to your templates so you can better identify where the allocations are coming from.&lt;br /&gt;&lt;br /&gt;So, here is how you actually use the MemoryTracker DLL in your application.&lt;br /&gt;&lt;br /&gt;You need three things:&lt;br /&gt;&lt;br /&gt;MemoryTracker.h&lt;br /&gt;MemoryTrackerBinding.cpp&lt;br /&gt;MemoryTracker.dll&lt;br /&gt;&lt;br /&gt;The header file 'MemoryTracker.h' defines the pure virtual interface to the memory tracking utility.&amp;nbsp; It also declares a single global variable pointer to the Memory tracking interface and a routine to initialize the DLL.&lt;br /&gt;&lt;br /&gt;In your code, before you do any memory allocations, initialize the MemoryTracker.dll by calling 'NVSHARE::createMemoryTracker("MemoryTracker.dll').&amp;nbsp;&amp;nbsp; You should pass the name of the DLL on disk, including the full path location if necessary.&lt;br /&gt;&lt;br /&gt;The routine 'createMemoryTracker' is in 'MemoryTrackerBinding.cpp' which will perfom a load library call on the DLL and initialize it; also setting the global variable 'gMemoryTracker'.&lt;br /&gt;&lt;br /&gt;Once the memory tracker DLL is loaded, you can now track all memory allocations performed by your project.&lt;br /&gt;&lt;br /&gt;First, set the logging detal level.&amp;nbsp; The options in 'setLogLevel' are:&lt;br /&gt;&lt;br /&gt;logEveryAllocation : This will produce an enormous amount of data, and is not recommended unless you really need to track every single allocation at startup.&lt;br /&gt;&lt;br /&gt;logEveryFrame : This will produce a summary of allocations and frees each frame.&amp;nbsp; For this to work you need to call the method 'trackFrame' once per logical 'frame' in your application.&amp;nbsp; Again, this feature is not recommended unless you are specifically wanting this data.&lt;br /&gt;&lt;br /&gt;There are three methods for tracking your memory allocations.&amp;nbsp; They are:&lt;br /&gt;&lt;br /&gt;'trackAlloc', 'trackRealloc', and 'trackFree'.&lt;br /&gt;&lt;br /&gt;The enum 'MemoryType' designates what was the type/purpose of each allocation.&amp;nbsp; This will identify if it was a 'new' 'delete', a 'new array' or 'delete array', or a 'global new', etc.&amp;nbsp; The difference between MT_NEW and MT_GLOBAL_NEW, is to indicate whether the new operator was trapped or not.&lt;br /&gt;&lt;br /&gt;When you track an allocation you can specify the class name, or simply a tag for the purpose/type of allocation, and the file name and line number of the original C++ source code.&amp;nbsp; You can do this by using the compiler preprocessor directive __FILE__ and __LINE__.&lt;br /&gt;&lt;br /&gt;It is very important to note that these string pointers must be persistent for the lifetime of your application!&amp;nbsp; You cannot, and should not, ever pass stack or temporary variables in as the parameters!&lt;br /&gt;&lt;br /&gt;One of the most valuable options when tracking memory is 'context'.&amp;nbsp; The 'context' allows you to organize your report based on its overall meaning within your application.&amp;nbsp; A good example of this is if you are working with a piece of middleware, like say the PhysX SDK, which allows you to provide a user allocator override.&amp;nbsp;&amp;nbsp; Every time this SDK does a callback to your application for memory you can pass in as the context field 'PhysX'.&amp;nbsp; Then, when you generate the memory report, you will have all of the memory used by PhyX organized separately from the memory allocated by other parts of your application.&lt;br /&gt;&lt;br /&gt;When you application exits, and after all memory allocated should have been freed, you can call the method 'detectMemoryLeaks'.&amp;nbsp; You pass it the filename of the HTML report you want saved.&amp;nbsp; Also you pass the option 'reportAllLeaks'.&amp;nbsp; If 'reportAllLeaks' is true then every single piece of allocated memory which was never freed will be reported in detail.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;In addition to using 'detectMemoryLeaks' to generate a report on exit, you may also call it at any time in your application simply to get a general report of overall memory usage.&lt;br /&gt;&lt;br /&gt;If you use it for this purpose it is strongly recommended that you set 'reportAllLeaks' to false, otherwise you could generate a massive data report.&lt;br /&gt;&lt;br /&gt;The real value of this utility is the report itself.&amp;nbsp; The output is sorted by class name, source code and line number, as well as context.&amp;nbsp; It comes with totals and subtotals and is some very nicely formatted HTML tables as output.&amp;nbsp; When I get a chance I will upload a sample report for you to take a look at. &lt;br /&gt;&lt;br /&gt;The MemoryTracker utility is an open source project hosted on Google Code.&amp;nbsp; You an find it at the &lt;a href="http://code.google.com/p/win32memorytracker/"&gt;following link&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If you don't care about the source code to the memory tracker tool but simply want to download the tool try these links.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/MemoryTracker.h"&gt;MemoryTracker.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/MemoryTrackerBinding.cpp"&gt;MemoryTrackerBinding.cpp&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/MemoryTracker.dll"&gt;MemoryTracker.dll&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-8741899550813095001?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/win32memorytracker/' title='Memory Tracking Utility'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/8741899550813095001/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=8741899550813095001' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8741899550813095001'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8741899550813095001'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2010/03/memory-tracking-utility.html' title='Memory Tracking Utility'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_PtTKwwh_xBc/S65l4efXKgI/AAAAAAAAG8M/y4KWFsZNeL4/s72-c/tumblr_kw8uwzRF7Z1qzr53co1_500.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-2814336882203425192</id><published>2010-03-25T10:44:00.000-07:00</published><updated>2010-03-25T10:44:29.336-07:00</updated><title type='text'>Any SIMD optimization specialist looking for some easy consulting work?</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_PtTKwwh_xBc/S6ugLqGaa5I/AAAAAAAAG8E/TduyxXVPlzU/s1600/photo.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://2.bp.blogspot.com/_PtTKwwh_xBc/S6ugLqGaa5I/AAAAAAAAG8E/TduyxXVPlzU/s400/photo.jpg" width="300" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Anyone in the game industry who has expertise at optimizing SIMD code for PC (SSE/3D Now,etc.) Xbox-360 Altivec, and PS3 SPU, looking for some easy money doing a short term gig, let me know.&lt;br /&gt;&lt;br /&gt;I have a handful of vanilla C++ routines which need to be optimized for these platforms using a shared math library.&amp;nbsp; It's not that I can't do it myself, it's that I am already over-committed on my time for a number of other projects.&amp;nbsp; Apparently I have the ability to pay a contractor to do some of the work, so this could be easy money for somebody who really enjoys doing low-level optimization work.&lt;br /&gt;&lt;br /&gt;&lt;a href="mailto:jratcliffscarab@gmail.com"&gt;Send me an email if you are interested.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-2814336882203425192?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/2814336882203425192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=2814336882203425192' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2814336882203425192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2814336882203425192'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2010/03/any-simd-optimization-specialist.html' title='Any SIMD optimization specialist looking for some easy consulting work?'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_PtTKwwh_xBc/S6ugLqGaa5I/AAAAAAAAG8E/TduyxXVPlzU/s72-c/photo.jpg' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-8133548705099736199</id><published>2010-03-21T12:25:00.000-07:00</published><updated>2010-03-21T12:33:17.163-07:00</updated><title type='text'>MapFile : A tool to analyze .MAP files produced by Visual Studio and report the amount of memory being used by data and code</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_PtTKwwh_xBc/S6ZwZ2y3MII/AAAAAAAAG70/d18VgFeNYN0/s1600-h/22.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://3.bp.blogspot.com/_PtTKwwh_xBc/S6ZwZ2y3MII/AAAAAAAAG70/d18VgFeNYN0/s400/22.jpg" width="296" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;It really annoys me that I had to write today's code snippet.&amp;nbsp; I fully expected to be able to find an existing tool that could accomplish this basic task but after literally a couple of hours of searching the Internet for something I gave up.&amp;nbsp; In the end I had to write my own tiny console application and I am making it available here so nobody else feels like they have to write it again.&lt;br /&gt;&lt;br /&gt;Also, if anyone reading this is really good at web stuff, it would be nice to have a website that would let you upload a .MAP file and then be able to immediately view the HTML content.&lt;br /&gt;&lt;br /&gt;The data in this version is pretty complete.&amp;nbsp; For some reason when I parse all of the address data found in the .MAP file it doesn't add up to the exact byte count that is in the sections summary.&amp;nbsp; Maybe somebody from Microsoft can explain why that is.&lt;br /&gt;&lt;br /&gt;The data could probably be a little better organized and it could really benefit from some hyperlinks.&amp;nbsp; That said, still all of the data you need is there.&lt;br /&gt;&lt;br /&gt;A .MAP file is an ASCII text file that can be produced by the linker phase in Visual Studio.&amp;nbsp; Under Linux the GCC compiler can also produce a .MAP file but I have no idea if the two formats are compatible.&amp;nbsp; For my needs I was only concerned about builds that were done with Visual Studio.&amp;nbsp; This works even if you are building for XBOX as well.&lt;br /&gt;&lt;br /&gt;A .MAP file is essentially a 'memory map' of the executable.&amp;nbsp; It describes by memory address every piece of code and data in the resulting executable file.&lt;br /&gt;&lt;br /&gt;Unfortunately it it not very human readable.&amp;nbsp; The function names in the map file are 'decorated'; meaning they have been scrambled/compressed into a machine only readable format.&amp;nbsp; A DLL that comes with Windows called 'dbghelp.dll' can 'undecorate' these strings into their human readable form.&lt;br /&gt;&lt;br /&gt;The MapFile console application will read in a .MAP file and output an HTML file called 'output.html' that contains tables representing all of the code and data sections in the executable.&lt;br /&gt;&lt;br /&gt;The tables are sorted either by object name or by function name.&lt;br /&gt;&lt;br /&gt;An executable is broken up into various 'section's and the HTML output is likewise broken up the same way.&lt;br /&gt;&lt;br /&gt;You might ask, why would you need this tool?&amp;nbsp; Well, I suppose that is a fair question.&amp;nbsp; Let's say you are targeting an Xbox-360 console machine and your executable size is 10 megabytes.&amp;nbsp; That's just huge.&amp;nbsp; So, you are going to want to know where all of that data coming from.&amp;nbsp; Is it code and, if so, from what source files and what functions?&amp;nbsp; Is it data and, if so, what kind of data is it and where is it located?&lt;br /&gt;&lt;br /&gt;I have set up a Google Project to host this tool.&amp;nbsp; You can find it at the following link:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/mapfile/"&gt;MapFile on Google Code&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Another reason you might want to download the source code to this tool is that it demonstrates how to use two of my most powerful code snippets.&amp;nbsp; The first is the 'InPlaceParser', which is an extremely high speed text parser and the second is 'HtmlTable' which is a code snippet that will output nicely formated HTMLTables with headers, sorted columns, and totals.&lt;br /&gt;&lt;br /&gt;Both code snippets are really useful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-8133548705099736199?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/mapfile/' title='MapFile : A tool to analyze .MAP files produced by Visual Studio and report the amount of memory being used by data and code'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/8133548705099736199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=8133548705099736199' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8133548705099736199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8133548705099736199'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2010/03/mapfile-tool-to-analyze-map-files.html' title='MapFile : A tool to analyze .MAP files produced by Visual Studio and report the amount of memory being used by data and code'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_PtTKwwh_xBc/S6ZwZ2y3MII/AAAAAAAAG70/d18VgFeNYN0/s72-c/22.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-4200468476494273662</id><published>2010-02-23T16:36:00.000-08:00</published><updated>2010-02-23T16:36:51.761-08:00</updated><title type='text'>PhysX Rocket for 2.8.3</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_PtTKwwh_xBc/S4R0E5xmnrI/AAAAAAAAG7Y/--wiqugjQyY/s1600-h/lrFgE.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/S4R0E5xmnrI/AAAAAAAAG7Y/--wiqugjQyY/s400/lrFgE.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The physics demo application, PhysX Rocket, has not been officially released in some time. &amp;nbsp;However, I frequently get questions from people who still enjoy playing with it as a tinker toy. &amp;nbsp;It can also be useful as a physics scripting application.&lt;br /&gt;&lt;br /&gt;Overall, Rocket is really showing its age. &amp;nbsp;It is very crufty, especially in terms of the source code.&lt;br /&gt;&lt;br /&gt;However, if you want a copy to play with, here is the link. &amp;nbsp;It is simply a ZIP file. &amp;nbsp;It does not have an installer, and does not include source code.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/rocket.zip"&gt;www.amillionpixels.us/rocket.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-4200468476494273662?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/4200468476494273662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=4200468476494273662' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/4200468476494273662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/4200468476494273662'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2010/02/physx-rocket-for-283.html' title='PhysX Rocket for 2.8.3'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/S4R0E5xmnrI/AAAAAAAAG7Y/--wiqugjQyY/s72-c/lrFgE.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-687503401242548600</id><published>2010-02-23T16:33:00.000-08:00</published><updated>2010-02-23T16:33:22.941-08:00</updated><title type='text'>NvCoreDump : Easily perform an NxuStream XML compatible core dump with PhysX 2.8.3</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_PtTKwwh_xBc/S4RyzxCNk2I/AAAAAAAAG7Q/yJDhZH5Psps/s1600-h/fat-cat.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="312" src="http://3.bp.blogspot.com/_PtTKwwh_xBc/S4RyzxCNk2I/AAAAAAAAG7Q/yJDhZH5Psps/s400/fat-cat.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;NvCoreDump is a windows 32 bit DLL which allows any PhysX 2.8.3 based project to perform an NxuStream XML compatible core dump in a single function call.&lt;br /&gt;&lt;br /&gt;Rather than including all of the NxuStream source code in your application, instead you can simply demand load this tiny DLL and save it out. &amp;nbsp;The value, purpose, and benefit is to take simply add the ability to export the contents of the current PhysX SDK in any application by simply adding this tiny code snippet and the DLL.&lt;br /&gt;&lt;br /&gt;This project is hosted on Google Code at the following location:&lt;br /&gt;&lt;br /&gt;&lt;a href="https://code.google.com/p/nvcoredump/"&gt;https://code.google.com/p/nvcoredump/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Simply add the source files 'NvCoreDump.h' and 'NvCoreDump.cpp' into your project. &amp;nbsp;Next add the DLL 'NvCoreDump283.dll' to your binary/executable directory.&lt;br /&gt;&lt;br /&gt;Somewhere in your project, typically when someone types a command at the console, simply call the method 'nvCoreDump' passing a pointer to the 2.8.3 PhysX SDK and a string pointer of the file name you want it saved as. &lt;br /&gt;&lt;br /&gt;The file will be saved in XML format as NxuStream. &amp;nbsp;NxuStream is a reflective object model representation of all of the internal data of the PhysX SDK, including scenes, meshes, constraints, clothing, and even fluids.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-687503401242548600?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/687503401242548600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=687503401242548600' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/687503401242548600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/687503401242548600'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2010/02/nvcoredump-easily-perform-nxustream-xml.html' title='NvCoreDump : Easily perform an NxuStream XML compatible core dump with PhysX 2.8.3'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_PtTKwwh_xBc/S4RyzxCNk2I/AAAAAAAAG7Q/yJDhZH5Psps/s72-c/fat-cat.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-959772588918746659</id><published>2010-02-23T16:23:00.000-08:00</published><updated>2010-02-23T16:23:42.661-08:00</updated><title type='text'>PhysX2Obj : Convert Physics Scenes into a Wavefront OBJ file</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_PtTKwwh_xBc/S4RvocecypI/AAAAAAAAG7I/BocKB438OTc/s1600-h/fs207500-14.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="306" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/S4RvocecypI/AAAAAAAAG7I/BocKB438OTc/s400/fs207500-14.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Today's code snippet might prove useful to anyone who works with the PhysX SDK. &amp;nbsp;This code has been compiled and tested with PhysX 2.8.3 but should work with earlier versions of the SDK with little or no modification.&lt;br /&gt;&lt;br /&gt;In any PhysX application simply include the header file 'PhysX2Obj.h' and invoke the single method 'exportPhysX2Obj'.&lt;br /&gt;&lt;br /&gt;You pass in a pointer to the scene you wish to export, the file name to save it as, and a bool indicating whether or not you want to export the data in world space or object space.&lt;br /&gt;&lt;br /&gt;If you select world space, you will simply get one large Wavefront OBJ file with all of the static geometry in your game level. &amp;nbsp;You can then import this Wavefront OBJ into 3D Studio Max or other tools for testing purposes.&lt;br /&gt;&lt;br /&gt;If you select object space, it will export all of the geometry in object space and annotate the file, with comments, indicating where each object should be instantiated in the world.&lt;br /&gt;&lt;br /&gt;Some of you might be familiar with my previous work on NxuStream; which is an XML file format that allows one to capture the state of a PhysX SDK scene. &amp;nbsp;However, that format required a large code base and could only be used in the context of the PhysX SDK.&lt;br /&gt;&lt;br /&gt;This tool is not a complete 'core dump' like NxuStream was; instead it is used primarily to export the gross game level geometry of an application so that it can be reviewed or debugged in another application.&lt;br /&gt;&lt;br /&gt;I have set up a Google Code page to host this code snippet. &amp;nbsp;You can find it here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/physx2obj/"&gt;http://code.google.com/p/physx2obj/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can also download the source directly using these two links. &amp;nbsp;However, the Google Code project will always be the most current copy.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/PhysX2Obj.cpp"&gt;PhysX2Obj.cpp&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/PhysX2Obj.h"&gt;PhysX2Obj.h&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Tomorrow I am going to write a code snippet 'Obj2PhysX' which will read one of these object files, either in world space or object space, and instantiate it on the PhysX SDK. &amp;nbsp;The code will be written in a generic enough fashion that you can also instantiate the data through some other API if you prefer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-959772588918746659?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/959772588918746659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=959772588918746659' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/959772588918746659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/959772588918746659'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2010/02/physx2obj-convert-physics-scenes-into.html' title='PhysX2Obj : Convert Physics Scenes into a Wavefront OBJ file'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/S4RvocecypI/AAAAAAAAG7I/BocKB438OTc/s72-c/fs207500-14.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-2025988717999117009</id><published>2009-12-03T07:15:00.001-08:00</published><updated>2009-12-03T07:21:39.296-08:00</updated><title type='text'>Two more compression libraries added to the test compression tool</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PtTKwwh_xBc/SxfWNo55jcI/AAAAAAAAGvE/U-Nij1AIE3E/s1600-h/compression.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 179px;" src="http://1.bp.blogspot.com/_PtTKwwh_xBc/SxfWNo55jcI/AAAAAAAAGvE/U-Nij1AIE3E/s400/compression.jpg" alt="" id="BLOGGER_PHOTO_ID_5411029007115849154" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A contributor, Mārtiņš Možeiko, just added support for two more compression libraries.  They are LZMA and FastLZ.  Click on the picture above to see the performance differences between the various compression libraries. &lt;br /&gt;&lt;br /&gt;As you can see it is pretty much a tie between several of the fast LZW style compressors.  I would recommend you use the one which has the most liberal license and the cleanest looking source code.&lt;br /&gt;&lt;br /&gt;I might, sometime soon, and some additional test cases.  The current test case is a 10mb XML file; which I thought was pretty representative of a big ASCII file you might hope to get some good compression out of.  I should also add some binary test cases as well.&lt;br /&gt;&lt;br /&gt;Thanks all for the contributions.  And, once again, here is the link to the &lt;a href="http://code.google.com/p/compressiontest/"&gt;compression test library&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-2025988717999117009?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/compressiontest/' title='Two more compression libraries added to the test compression tool'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/2025988717999117009/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=2025988717999117009' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2025988717999117009'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2025988717999117009'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/12/two-more-compression-libraries-added-to.html' title='Two more compression libraries added to the test compression tool'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_PtTKwwh_xBc/SxfWNo55jcI/AAAAAAAAGvE/U-Nij1AIE3E/s72-c/compression.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-5041744928119391629</id><published>2009-12-02T11:59:00.000-08:00</published><updated>2009-12-02T12:19:22.089-08:00</updated><title type='text'>Compression Test</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_PtTKwwh_xBc/SxbHcqgHjfI/AAAAAAAAGu0/B-EQukAlCmY/s1600-h/XQ4A8GalLf7aloh5qwTxVhUAo1_500.jpg"&gt;&lt;img style="cursor: pointer; width: 266px; height: 400px;" src="http://2.bp.blogspot.com/_PtTKwwh_xBc/SxbHcqgHjfI/AAAAAAAAGu0/B-EQukAlCmY/s400/XQ4A8GalLf7aloh5qwTxVhUAo1_500.jpg" alt="" id="BLOGGER_PHOTO_ID_5410731297591496178" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Back in March of 2008 I made a posting about comparing various open source compression libraries.  You can read the &lt;a href="http://codesuppository.blogspot.com/2008/03/compression-decompression-comparing.html"&gt;original post at this link.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I don't get a lot of feedback about this coding website.  That doesn't bother me because I upload stuff here as much for myself as anyone else.  Over the years I have taken advantage of a lot of source code other developers have written and posted on the Internet.  It is for this reason that I feel a sincere debt that I should contribute back as often as I can.&lt;br /&gt;&lt;br /&gt;I use the various code snippets and projects I host on this site for my own personal needs all of the time so I don't really need feedback that other people find them useful for me to continue uploading stuff.&lt;br /&gt;&lt;br /&gt;Nevertheless, it is quite gratifying when someone does give me feedback that they found something useful.  The most gratifying experience of all is when someone made bug fixes and/or improvements to something I have posted; that is the ultimate reward.&lt;br /&gt;&lt;br /&gt;Yesterday I received an email from Anthony Whitaker who updated the compression test app to support a new format that is faster than MiniLZO and does not have a restrictive license.&lt;br /&gt;&lt;br /&gt;Anthony also wanted me to mention that "&lt;span dir="ltr" id=":2nu"&gt;The LZMA SDK from 7zip is also in the freeware domain. And 7zip seems quite fast (relative to Rar and Winzip)&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;The new format that Anthony added is &lt;a href="http://oldhome.schmorp.de/marc/liblzf.html"&gt;Marc Lehmann's LibLZF&lt;/a&gt;.  This is a very impressive tiny library which is extremely fast and lightweight.  It is hands down the winner of all of the compression libraries already added to the test framework.&lt;br /&gt;&lt;br /&gt;If you feel you have a better one, feel free to modify the compression test library to support your format.  Let me know if you want to be a project member of the Google Code site.&lt;br /&gt;&lt;br /&gt;The official location of the compression test library is &lt;a href="http://code.google.com/p/compressiontest/"&gt;located here on Google Code&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For the record, the compression test library now supports:&lt;br /&gt;&lt;br /&gt;CRYPTOPP&lt;br /&gt;MINILZO&lt;br /&gt;ZLIB&lt;br /&gt;BZIP&lt;br /&gt;and now LIBLZF&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-5041744928119391629?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/compressiontest/' title='Compression Test'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/5041744928119391629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=5041744928119391629' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/5041744928119391629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/5041744928119391629'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/12/compression-test.html' title='Compression Test'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_PtTKwwh_xBc/SxbHcqgHjfI/AAAAAAAAGu0/B-EQukAlCmY/s72-c/XQ4A8GalLf7aloh5qwTxVhUAo1_500.jpg' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-847110470830820669</id><published>2009-11-30T15:35:00.000-08:00</published><updated>2011-05-20T13:18:37.115-07:00</updated><title type='text'>Convex Decomposition Library now available on Google Code</title><content type='html'>&lt;a href="http://4.bp.blogspot.com/_PtTKwwh_xBc/SxRW8t3nbtI/AAAAAAAAGus/jhChPeBDj2Y/s1600/composite.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5410044653483814610" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/SxRW8t3nbtI/AAAAAAAAGus/jhChPeBDj2Y/s400/composite.jpg" style="cursor: pointer; height: 400px; width: 337px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;***NOTICE ** NOTICE ** My convex decomposition library is now deprecated.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://codesuppository.blogspot.com/2011/05/hacd-hierarchical-approximate-convex.html"&gt;Please see this blog post for further details.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Today I refactored my convex decomposition code into the form of a 'drop in' library that people can use.  Here is a link to the &lt;a href="http://code.google.com/p/convexdecomposition/"&gt;Google Code repository.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You need only include a single header file 'NvConvexDecomposition.h' to use the tool.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%; font-weight: bold;"&gt;What is convex decomposition?&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Convex decomposition is the process of taking an arbitrarily complex concave triangle mesh and approximating it as a collection of convex objects.&lt;br /&gt;&lt;br /&gt;See the image above to for an example of how an approximate convex decomposition can, depending on the recursion depth and other factors, accurately represent a collision model for a triangle mesh.  There are no hard and cold set of parameters to use for all triangle meshes; how detailed you make the approximate decomposition is always going be dependent on your specific use case.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%;"&gt;&lt;span style="font-weight: bold;"&gt;Why do I need it?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Most physics engines will not allow you to represent arbitrary triangle meshes as dynamic objects.  Even if the physics/collision engine does support arbitrary triangle mesh collision, it always comes at a major cost in terms of performance and memory.&lt;br /&gt;&lt;br /&gt;Therefore, if you have complex triangle meshes that you wish to be realistically simulated in a dynamic world the best solution is to substitute it for a collection of compound convex hulls.&lt;br /&gt;&lt;br /&gt;The physics engine will see the collection of convex hulls for collision while the graphics displays the original source triangle mesh for the viewer.  Depending on how accurately your compound convex hulls match the source graphics you may, or may not, see some small artifacts.  The choice of how detailed to make the approximation is almost always a design decision based on your specific use case.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%;"&gt;&lt;span style="font-weight: bold;"&gt;How do I use it?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I am providing the Convex Decomposition library as a relatively small collection of source code that resides in its own namespace.  The source code is C++ and is in the namespace 'CONVEX_DECOMPOSITION'.  Even though there are a number of CPP and header files you only need to include a single header file to use the library.&lt;br /&gt;&lt;br /&gt;Simply include 'NvConvexDecomposition.h'&lt;br /&gt;&lt;br /&gt;Create an instance of the library:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;CONVEX_DECOMPOSITION::iConvexDecomposition *ic = CONVEX_DECOMPOSITION::createConvexDecomposition();&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Next, add the triangles from the original raw triangle mesh you wish to approximate.&lt;br /&gt;&lt;br /&gt;You add them one triangle at a time, passing in three const float pointers, each representing a single X,Y,Z co-ordinate in the original triangle mesh.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;for (NxU32 i=0; i&lt;tcount; i++)="" ic-=""&gt;addTriangle( tris[i].p0, tris[i].p1, tris[i].p2 );&lt;br /&gt;&lt;/tcount;&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Once you have added all of the triangles you can compute the convex decomposition as follows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;ic-&amp;gt;computeConvexDecomposition(skinWidth,&lt;br /&gt;decompositionDepth,&lt;br /&gt;maxHullVertices,&lt;br /&gt;concavityThresholdPercent,&lt;br /&gt;mergeThresholdPercent,&lt;br /&gt;volumeSplitThresholdPercent,&lt;br /&gt;useInitialIslandGeneration,&lt;br /&gt;useIslandGeneration,&lt;br /&gt;useBackgroundThreads);&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The convex decomposition process can take a very long time.  For this reason the default behavior is to perform the computation in a background thread.&lt;br /&gt;&lt;br /&gt;You will have to query: '&lt;span style="font-style: italic;"&gt;isComputeComplete&lt;/span&gt;' to know when it has finished.&lt;br /&gt;&lt;br /&gt;If you want to interrupt the computation before it is done you can call '&lt;span style="font-style: italic;"&gt;cancelCompute&lt;/span&gt;'&lt;br /&gt;&lt;br /&gt;To find out how many convex hulls were produced you call: '&lt;span style="font-style: italic;"&gt;getHullCount&lt;/span&gt;'&lt;br /&gt;&lt;br /&gt;You can then iterate through the hull results and grab each one as needed: '&lt;span style="font-style: italic;"&gt;getConvexHullResult&lt;/span&gt;'&lt;br /&gt;&lt;br /&gt;When you are finished using the library, simply call:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;CONVEX_DECOMPOSITION::releaseConvexDecomposition(ic);&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-size: 130%;"&gt;&lt;span style="font-weight: bold;"&gt;What are the current limitations of this implementation?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The code is functional but could use the following improvements:&lt;br /&gt;&lt;br /&gt;(1) The convex hull generator, originally written by Stan Melax, could use some major code cleanup.&lt;br /&gt;&lt;br /&gt;(2) The code to remove T-junctions appears to have a bug in it.  This code was working fine before, but I haven't had time to debug why it stopped working.&lt;br /&gt;&lt;br /&gt;(3) Island generation once the mesh has been split is currently disabled due to the fact that the Remove Tjunctions functionality has a bug in it.&lt;br /&gt;&lt;br /&gt;(4) The code to perform a raycast against a triangle mesh does not currently use any acceleration data structures.&lt;br /&gt;&lt;br /&gt;(5) When a split is performed, the surface that got split is not 'capped'.  This causes a problem if you use a high recursion depth on your convex decomposition.  It will cause the object to be modelled as if it had a hollow interior.  A lot of work was done to solve this problem, but it hasn't been integrated into this code drop yet.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%;"&gt;&lt;span style="font-weight: bold;"&gt;When will these limitations be fixed?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It is hard to say.  The current version is functional and I don't foresee having a lot of time to work on this any time soon.  If a specific need arises I may get back to it sooner.  I definitely want to add the acceleration structures to the raycast routine; which will speed things up.  I also really want to know why the remove tjunctions code has a bug in it, since that was working fine before.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%;"&gt;&lt;span style="font-weight: bold;"&gt;What is all of this source code, what is it for?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As I said before, you only need to include 'NvConvexDecomposition.h' and nothing else to use the library.  I will, however, document what the other pieces of source code are and what purpose they serve.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;NvConcavityVolume.h / .cpp&lt;/span&gt; : Computes the 'volume of concavity' of a triangle mesh.  It does this by first computing the convex hull for this triangle mesh.  Next, it examines every single individual triangle in the original mesh and 'projects it' onto both the convex hull and on itself.  If the projection hits the hull, then that extruded triangle volume is added as part of the 'total concavity volume'.  It the projection hits the mesh itself, it first determines if it hit an interior or exterior face.  If it hits an interior face, the volume is rejected.  Otherwise, it adds to the volume of concavity the projection up to the point of self-intersection.  This would be easier to explain with some drawings and pictures but I don't have time to make those up right now.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;NvConvexDecomposition.h / .cpp&lt;/span&gt; : This is the main public interface to the convex decomposition library.  This is the only header your application should need to include directly.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;NvFloatMath.h / .cpp / .inl&lt;/span&gt; : This contains a collection of common and useful math library routines which work of of either const float or const double pointers.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;NvHashMap.h &lt;/span&gt;: This single header file contains support for both vector and hashmap container template classes.  The reason this header file is used is because some of the game engine integrations that I work on do not allow the use of the STL at all.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;NvMeshIslandGeneration.h / .cpp&lt;/span&gt; : This is a code snippet which walks the topology of a triangle mesh, effectively flood filling it along the edges, to compute all of the independent mesh islands.  Let's take the simple case.  You pass in a single triangle mesh which actually contains two separate boxes.  By walking the topology of the mesh the NvMeshIslandGeneration code snippet would immediately identify these as two distinctly unique triangle meshes.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;NvRayCast.h / .cpp&lt;/span&gt; : This code snippet provides based support to cast a ray against an arbitrary triangle mesh.  Ideally it would use acceleration structures (such as an axis-aligned bounding volume tree).  The current version does not yet have this optimization built in.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;NvRemoveTjunctions.h / .cpp&lt;/span&gt; : This code snippet is designed to identify and remove T-junctions in the triangle mesh.  After a triangle mesh has been split by a plane it is common for t-junctions to be introduced.  However, if you wish to continue to walk the topology of the mesh, either to identify mesh islands or to generate capped ends, there can be no t-junctions allowed in the mesh.  This routine was not working properly when I put the library together so is currently disabled.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;NvSimpleTypes.h&lt;/span&gt; : This is a tiny header file that creates a set of platform and compiler independent standard defines for integer and floating point data types.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;NvStanHull.h / .cpp&lt;/span&gt; : Contains the convex hull generation code written originally by Stan Melax.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;NvThreadConfig.h / .cpp&lt;/span&gt; : This is a small code snippet that provides a platform independent abstraction for creating threads and mutexes.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;NvUserMemAlloc.h&lt;/span&gt; : This is a simple header file that controls how memory allocation is performed by this library.  The default behavior is to use malloc/free and global new/delete.  However, you can modify this header file to redirect memory allocations performed by this library to vector off to your application specific memory allocator if needed.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;wavefront.h / cpp &lt;/span&gt;: This is a tiny code snippet to read a Wavefront OBJ triangle mesh file.  It is not considered part of the convex decomposition library and is only included for the sample application.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;main.cpp&lt;/span&gt; : This is a basic sample application that shows how to use the convex decomposition library by loading a triangle mesh from a Wavefront OBJ and uses command line switches to experiment with different parameters.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-size: 130%;"&gt;&lt;span style="font-weight: bold;"&gt;How does the convex decomposition algorithm work?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The convex decomposition algorithm works as follows.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The input mesh has any possible t-junctions removed to make sure that it has a clean topology. (Currently disabled)&lt;/li&gt;&lt;li&gt;The input mesh is broken up into any unique mesh islands.  This is collection of triangles which all share edges.  (Currently only enabled on the initial triangle mesh)&lt;/li&gt;&lt;li&gt;For each mesh island we do the following steps.&lt;/li&gt;&lt;li&gt;We compute the overall volume of the triangle mesh.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Make sure we have not exceeded our maximum decomposition depth, if we have, we are done.&lt;/li&gt;&lt;li&gt;We compute the volume of the current part of the mes we are working on.  We then calculate what percentage the volume of this piece is, relative to the volume of the entire object.  It the volume is too small (based on the input parameter 'volumeSplitThresholdPercent' then we are done with this piece.&lt;/li&gt;&lt;li&gt;Next we compute the 'volume of concavity'.  This is done by building a  convex hull around this piece of the mesh and then projecting the volume of each triangle on the original mesh onto either the mesh itself or the surrounding convex hull.  The sum total is represented as the 'volume of concavity'.&lt;/li&gt;&lt;li&gt;We compute what percentage the volume of concavity is relative ot the volume of the surrounding convex hull.  This percentage is then compared against the input parameter 'concavityThresholdPercent'.  If the volume percentage of concavity is below this threshold we consider it 'good enough' and accept this piece as is.&lt;/li&gt;&lt;li&gt;If we have determined that the mesh piece is too concave we split it in half.  First we compute the best fit OBB (object oriented box) around the convex hull of this piece.  We create a split plane exactly half way along the long axis.  (Other techniques for performing approximate convex decomposition have focused a lot of work finding just the absolutely perfect split plane to use.  As you will see later, this algorithm doesn't require that.)&lt;/li&gt;&lt;li&gt;Once we have split the mesh by the plan we need to cap the ends so that the two pieces do not have holes in them.  If we do not cap the ends then, as we recurse more deeply we will end up producing a hollow interior.  &lt;span style="font-style: italic;"&gt;It is important to note that this feature is not yet implemented!  A lot of work has been done on this process and quite likely the library will be revised to support this feature at some time in the future.&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Having split the mesh at the mid-point we just keep recursively calling the routine until we have exceeded our maximum recursion depth and/or other limits specified.&lt;/li&gt;&lt;li&gt;The final step is critical.  Since we split each piece on the long axis of its orientation there is no guarantee that we split at exactly the correct location.   We make up for this by actually splitting the source mesh many more times that is necessary.  The final clean-up phase called 'merging' corrects for this.&lt;/li&gt;&lt;li&gt;For every hull we have generated we try combining it with every other hull in the decomposition.  We compute the volume of the two hulls separately and compare that to the volume of the two hulls combined.  If the difference in volume is below the parameter 'mergeThresholdPercent' than we combine the two hulls into one.  We continue this process until we can no longer merge any hulls.  In a brute force manner this technique causes the merged hulls to converge towards the optimal split boundaries.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-847110470830820669?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/convexdecomposition/' title='Convex Decomposition Library now available on Google Code'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/847110470830820669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=847110470830820669' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/847110470830820669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/847110470830820669'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/11/convex-decomposition-library-now.html' title='Convex Decomposition Library now available on Google Code'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/SxRW8t3nbtI/AAAAAAAAGus/jhChPeBDj2Y/s72-c/composite.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-2041039939703676846</id><published>2009-11-19T15:34:00.001-08:00</published><updated>2009-11-19T15:38:18.765-08:00</updated><title type='text'>ThreadFrac revised</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_PtTKwwh_xBc/SwXWLWze1uI/AAAAAAAAGuU/GEGEC-EVWaU/s1600/5731_263484590200_896320200_8359062_7807823_n.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 300px; height: 400px;" src="http://3.bp.blogspot.com/_PtTKwwh_xBc/SwXWLWze1uI/AAAAAAAAGuU/GEGEC-EVWaU/s400/5731_263484590200_896320200_8359062_7807823_n.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5405962418316564194" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Grrr...I went to run my copy of 'ThreadFrac' that was uploaded in a couple of places and it wouldn't run due to side-by-side assembly issues or some such nonsense.&lt;br /&gt;&lt;br /&gt;I rebuilt it with an embedded manifest and it should run now.&lt;br /&gt;&lt;br /&gt;Let me know if you have a problem; requires Windows with DX9 to run.&lt;br /&gt;&lt;br /&gt;The reason I was looking for ThreadFrac is that I want to start messing with the new 3d equation called 'Mandelbulb'.&lt;br /&gt;&lt;br /&gt;I'm going to write a real-time multi-threaded raytracer and add it to my ThreadFrac program when I get a chance to work on.&lt;br /&gt;&lt;br /&gt;If you haven't seen the '&lt;a href="http://www.skytopia.com/project/fractal/mandelbulb.html"&gt;Mandelbulb&lt;/a&gt;' yet, check it out.&lt;br /&gt;&lt;br /&gt;Here is the link to the revised executable for &lt;a href="http://aarm.mywowbb.com/ThreadFrac.zip"&gt;ThreadFrac.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-2041039939703676846?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://aarm.mywowbb.com/ThreadFrac.zip' title='ThreadFrac revised'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/2041039939703676846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=2041039939703676846' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2041039939703676846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2041039939703676846'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/11/threadfrac-revised.html' title='ThreadFrac revised'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_PtTKwwh_xBc/SwXWLWze1uI/AAAAAAAAGuU/GEGEC-EVWaU/s72-c/5731_263484590200_896320200_8359062_7807823_n.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-313398334117792314</id><published>2009-11-05T10:07:00.001-08:00</published><updated>2009-11-05T21:59:41.701-08:00</updated><title type='text'>A test application for the MeshImport library and showcasing EZMesh</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_PtTKwwh_xBc/SvMUsgey0ZI/AAAAAAAAGt4/LiLjGjQF9ME/s1600-h/wow5.jpg"&gt;&lt;img style="cursor: pointer; width: 390px; height: 335px;" src="http://2.bp.blogspot.com/_PtTKwwh_xBc/SvMUsgey0ZI/AAAAAAAAGt4/LiLjGjQF9ME/s400/wow5.jpg" alt="" id="BLOGGER_PHOTO_ID_5400683133013250450" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I spent some time this morning and created a really nice sample program to demonstrate how to use the MeshImport plugins.  (Here is a link to the formal documentation for the &lt;a href="http://docs.google.com/View?id=d5v2g3t_18csmgsxc7"&gt;EZ-Mesh file format&lt;/a&gt;.  It is a work in progress but should be finished up tomorrow)&lt;br /&gt;&lt;br /&gt;The MeshImport plugin library provides an easy mechanism to both import and export fully skeletal deformed and animated mesh content.&lt;br /&gt;&lt;br /&gt;It supports multiple graphics file formats but I am strongly recommending the EZMesh graphics file format.&lt;br /&gt;&lt;br /&gt;I describe the reasons for this in the enclosed readme.&lt;br /&gt;&lt;br /&gt;The readme can be found at this link:  &lt;a href="http://www.amillionpixels.us/MeshImportReadme.txt"&gt;MeshImportReadme.txt&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;An example of an EZ-Mesh file which describes a skeleton, an animation, and a deformed mesh, can be found at the following link.  In only 34 lines of XML it is able to describe all of the components necessary to a skeletal deformed (and animated) mesh in a highly human readable format.  Let's see COLLADA (or any other graphics file format) try doing that.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/export.ezm"&gt;EXPORT.EZM&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To download the sample application, with all of the necessary DLL components, use this link:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/MeshImportTest.zip"&gt;MeshImportTest.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can browse the sample demonstration source code here, so see how easy it is to actually use the MeshImport library.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/main.cpp"&gt;main.cpp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Documentation for the Ez-Mesh &lt;a href="http://docs.google.com/View?id=d5v2g3t_18csmgsxc7"&gt;file format&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here are some more important links:&lt;br /&gt;&lt;br /&gt;Here is the link to a Google Code project containing the &lt;a href="http://code.google.com/p/meshimporttest/"&gt;Mesh Import test application.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you are interested in building the plugins, or perhaps writing a new mesh importer.  I have recently updated the source in the Google Code project.&lt;br /&gt;&lt;br /&gt;The Google Code project for the &lt;a href="http://code.google.com/p/meshimport/"&gt;Mesh Import libraries is located here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Once you sync, to build the project load the solution file in:&lt;br /&gt;&lt;br /&gt;\MeshImport\compiler\vc8\MeshConvert.sln&lt;br /&gt;&lt;br /&gt;The FBX importer is not built by default, because it is dependent on the FBX SDK  from Autodesk which you &lt;a href="http://usa.autodesk.com/adsk/servlet/index?siteID=123112&amp;amp;id=7478532"&gt;must obtain here&lt;/a&gt;.  None of the other importers contain any external dependencies.&lt;br /&gt;&lt;br /&gt;The solution file for the FBX importer is located in:&lt;br /&gt;&lt;br /&gt;\MeshImport\compiler\vc8\MeshImportFBX.sln&lt;br /&gt;&lt;br /&gt;You will need to change the include paths to point to wherever you have the FBX SDK on your machine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-313398334117792314?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/meshimporttest/' title='A test application for the MeshImport library and showcasing EZMesh'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/313398334117792314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=313398334117792314' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/313398334117792314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/313398334117792314'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/11/test-application-for-meshimport-library.html' title='A test application for the MeshImport library and showcasing EZMesh'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_PtTKwwh_xBc/SvMUsgey0ZI/AAAAAAAAGt4/LiLjGjQF9ME/s72-c/wow5.jpg' height='72' width='72'/><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-882194948153375149</id><published>2009-10-23T10:45:00.000-07:00</published><updated>2009-10-23T10:51:10.083-07:00</updated><title type='text'>Bug Fixes : Improvements to 'FastXml'</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PtTKwwh_xBc/SuHr8GaQEWI/AAAAAAAAGiw/q1R8kcMFKok/s1600-h/025_pics.jpg"&gt;&lt;img style="cursor: pointer; width: 309px; height: 400px;" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/SuHr8GaQEWI/AAAAAAAAGiw/q1R8kcMFKok/s400/025_pics.jpg" alt="" id="BLOGGER_PHOTO_ID_5395853246311960930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I made a couple of bug fixes and improvements to the 'FastXml' code snippets.  'FastXml' is a very tiny code snippet (less than 300 lines of code) that will parse an XML file *in place*.  It is very fast and easy to use.&lt;br /&gt;&lt;br /&gt;The 'in place' behavior is what makes it extremely powerful.  When it calls back with elements, attributes, and data, those pointers are *persistent for the lifetime of the object*!  That means you do not need to do any string copying and can cache those pointers directly if it speeds up your processing code.&lt;br /&gt;&lt;br /&gt;The bugs which were fixed are as follows:&lt;br /&gt;&lt;br /&gt;(1) The original version had a bug that if you had an element with no attributes or data it would fail.  Example:  &lt;foo/&gt;&lt;br /&gt;&lt;br /&gt;(2) The original version could not interpret XML comments.  It now does, and will call you back with the comment data.  Example: &lt;!--  This is an XML comment --&gt;&lt;br /&gt;&lt;br /&gt;The feature improvement is that it will now call you back when an element is closed.  This is sometimes necessary when parsing data with hierarchical state.  Not typically necessary if you are just parsing the XML data as a linear stream.&lt;br /&gt;&lt;br /&gt;I have updated the source files and they are located here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FastXml.h"&gt;FastXml.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FastXml.cpp"&gt;FastXml.cpp&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-882194948153375149?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/882194948153375149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=882194948153375149' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/882194948153375149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/882194948153375149'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/10/bug-fixes-improvements-to-fastxml.html' title='Bug Fixes : Improvements to &apos;FastXml&apos;'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/SuHr8GaQEWI/AAAAAAAAGiw/q1R8kcMFKok/s72-c/025_pics.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-8265523950049557092</id><published>2009-09-29T08:20:00.001-07:00</published><updated>2009-09-29T09:45:43.832-07:00</updated><title type='text'>Memory allocations are not 'bad'  Debunking the myth</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_PtTKwwh_xBc/SsIl1NBltPI/AAAAAAAAGiY/-HzDqu_4yRo/s1600-h/3rEkEGIaqqbac5l220s3o4Myo1_500.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 400px;" src="http://2.bp.blogspot.com/_PtTKwwh_xBc/SsIl1NBltPI/AAAAAAAAGiY/-HzDqu_4yRo/s400/3rEkEGIaqqbac5l220s3o4Myo1_500.jpg" alt="" id="BLOGGER_PHOTO_ID_5386909700248155378" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I recently had a conversation with an engineer at a game company where he expressed annoyance that his development team was using that &lt;span style="font-style: italic;"&gt;damned STL&lt;/span&gt; (STLPort in particular).  I asked why and he felt that way.  His response was that he couldn't stand how much memory allocation that the STL was doing.  He also expressed annoyance that the performance of STL map was so slow and his programmers kept using it.&lt;br /&gt;&lt;br /&gt;This raises a couple of points.  First of all, there is rarely a reason to use STL map.  The STL map/set is a red-black tree.  The only reason you would ever use it is if you needed to maintain a set of objects in perfectly sorted order.  This use case doesn't come up a lot, though, and most people are using it just to do key/value lookups.  However, if all you want is a key/value lookup you should instead be using the hash_map.&lt;br /&gt;&lt;br /&gt;What I really want to address in this post is the myth that 'memory allocations' are 'bad'.&lt;br /&gt;&lt;br /&gt;What does someone mean by 'bad'?&lt;br /&gt;&lt;br /&gt;I think what the mean is as follows:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Memory allocations are slow&lt;/li&gt;&lt;li&gt;Memory allocations cause fragmentation&lt;/li&gt;&lt;li&gt;Memory allocations cause thread contention&lt;/li&gt;&lt;li&gt;Memory allocations have way too much overhead&lt;/li&gt;&lt;li style="text-align: left;"&gt;Memory allocations are not cache-coherent&lt;/li&gt;&lt;/ul&gt;Developers often hold these assumptions, but are they really true?&lt;br /&gt;&lt;br /&gt;What if none of these things were true?  Then, do you really have a valid complaint about how many allocations the STL is doing, or your other container classes?&lt;br /&gt;&lt;br /&gt;With the micro-allocator I presented in the previous post, none of these criticisms are really valid.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Myth #1 : Memory allocations are slow &lt;/span&gt;:  With the micro-allocator I presented memory allocations, and frees, are extraordinarily fast.  A memory allocation simply involves returning a free pointer from a linked list 99.9999% of the time.&lt;br /&gt;&lt;br /&gt;One reason people sometimes think that memory allocators are slow is...because they are *&lt;span style="font-style: italic;"&gt;when running in a debugger in a debug build&lt;/span&gt;*.   It is important to measure real performance outside of the debugger and in a release build when considering the cost of your memory allocation system.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Myth #2 : Memory allocations cause fragmentation &lt;/span&gt;:  The design of my micro-allocator is that you give it a budget which is equal to an estimate of the maximum amount of memory needed for micro-allocations by your application.  This is allocated a single time and carved up in power of two multiples.  The allocator works within this single fixed block of memory and, so long as you do not exceed the budget estimate, it will never range outside this block of memory.  No fragmentation, in the sense of memory being returned from all over the address space, will occur.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Myth #3 : Memory allocations cause thread contention :&lt;/span&gt;  Last year when I was working on my JobSwarm code snippet I spent some time making sure it worked with a lockless queue.  Once I had this working I tried to create a benchmark that would show the performance benefit of a lockless queue versus a standard mutex lock.  What I found, is that it was very difficult to create a scenario where any significant performance distinction could be measured.  It turns out, that unless you have an application which is spending almost all of its time in contention, you can't even quantify a benefit.  Add to this the fact that my micro-allocator is so fast, usually just taking a few instruction cycles, any contention from a thread lock is going to be very small unless the only thing your application does *is* memory allocation in multiple threads simultaneously.&lt;br /&gt;&lt;br /&gt;All that said, ideally a micro-allocator should entirely avoid or minimize thread contention.  There are commercial micro-allocators that do this.  The most well known is &lt;a href="http://www.hoard.org/"&gt;The Hoard Memory Allocator.&lt;/a&gt;  Hoard is specifically designed to be highly efficient in multi-threaded environments.  Also, as we move to more and more cores and, therefore more and more simultaneous threads, minimizing thread contention is important.&lt;br /&gt;&lt;br /&gt;For my current implementation of the micro-allocator I just threw a mutex lock around the allocation and free routines.  This was a quick and lazy approach to the problem though, as I said before, I doubt it is even an issue in most scenarios.  That said, I would like to optimize it to be lockless, or near lockless, in the future.  (It appears that I can download an evaluation copy of Hoard so sometime in the next week or two I will try to run benchmarks between it and my micro-allocator and I will report the results.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Myth #4 : Memory allocations have way too much overhead&lt;/span&gt; : Most memory allocators will stick a header block in front of every allocation.  This header block will often include linked list pointers and possibly a sentinel in a debug build.&lt;br /&gt;&lt;br /&gt;The micro-allocator I presented, however, does not introduce any additional overhead.  If you allocate 8 bytes, it takes exactly 8 bytes of memory.  If you allocate 16 bytes, it takes exactly 16 bytes, etc.  Now, if you allocate 14 bytes, it will, in fact, return a block of memory that is actually 16 bytes in length (the nearest power of two) thus 'wasting' the 2 bytes in between.&lt;br /&gt;&lt;br /&gt;Perhaps the micro-allocator could be considered as having 'too much overhead' in the sense that it is a power of two allocator and always rounds up to the nearest power of two boundary.  However, since it works primarily in a fixed budget of memory for small allocations, this is probably acceptable.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Myth #5 : Memory allocations are not cache-coherent&lt;/span&gt; : My micro-allocator is a power of two allocator and, especially since it requires no header block, always returns cache aligned blocks of memory.  Any allocations of small objects in a sequence will naturally end up sequentially in the same area of memory.&lt;br /&gt;&lt;br /&gt;All allocations 16 bytes to 256 bytes in size will be perfectly aligned on a page boundary.  8 byte allocations will lie on an 8 byte boundary or, every other one, 16 bytes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The point I am trying to make here is that the concerns people have about using the STL, or other containers which do per-object allocations, are largely irrelevant *if* you have a high-speed micro-allocator under the hood.&lt;br /&gt;&lt;br /&gt;There is no need to make special containers and special small object allocators if you have confidence that your core allocator already has these behaviors built right in.&lt;br /&gt;&lt;br /&gt;Over the course of the next few months I plan to be doing some optimizations on console platforms using the micro-allocator I wrote and will be reporting any performance numbers I come up with.&lt;br /&gt;&lt;br /&gt;So far I have only tested it extensively on the PC and it really doesn't show any performance difference between standard malloc/free which, as I pointed out earlier, is surprisingly fast anyway.&lt;br /&gt;&lt;br /&gt;The lesson to be learned is that you shouldn't complain about the 'cost' of lots of tiny memory allocations until you know for fact that your application is really feeling a legitimate cost.  If you find that there is a significant cost by using the standard library malloc/free, don't resort to writing a bunch of custom allocators and template code until you have evaluated a high performance general purpose small object allocator like &lt;a href="http://www.hoard.org/"&gt;Hoard&lt;/a&gt;, &lt;a href="http://g.oswego.edu/dl/html/malloc.html"&gt;Doug Lea's malloc, or my own micro allocator I have posted here.&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-8265523950049557092?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/8265523950049557092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=8265523950049557092' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8265523950049557092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8265523950049557092'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/09/memory-allocations-are-not-bad.html' title='Memory allocations are not &apos;bad&apos;  Debunking the myth'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_PtTKwwh_xBc/SsIl1NBltPI/AAAAAAAAGiY/-HzDqu_4yRo/s72-c/3rEkEGIaqqbac5l220s3o4Myo1_500.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-3367399285049996187</id><published>2009-09-06T11:54:00.001-07:00</published><updated>2009-09-07T14:59:09.525-07:00</updated><title type='text'>A free open source micro allocator in C++</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_PtTKwwh_xBc/SqQFiklmi5I/AAAAAAAAGhE/21_i_8Gsgwg/s1600-h/yX6zGzbltr05hzkrRsvBjbUdo1_500.jpg"&gt;&lt;img style="cursor: pointer; width: 314px; height: 400px;" src="http://3.bp.blogspot.com/_PtTKwwh_xBc/SqQFiklmi5I/AAAAAAAAGhE/21_i_8Gsgwg/s400/yX6zGzbltr05hzkrRsvBjbUdo1_500.jpg" alt="" id="BLOGGER_PHOTO_ID_5378429946482297746" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;My code snippet today is a free open source micro-allocator.  As many of you know, using the STL (or containers in general) will cause many,many, tiny allocations to be performed.  Even just in a standard game engine, you will constantly be doing lots of small allocations for objects.&lt;br /&gt;&lt;br /&gt;Now, some people work around this by writing custom pool allocators.  However, that is not really necessary.  If you have an efficient general purpose micro-allocator that is 'order-N' you can bank on the fact that it is always available.  Don't worry about how much a memory allocation costs if it is less than or equal to 256 bytes in size.  Don't worry about it not being cache aligned or cache-coherent.  That will happen automatically.&lt;br /&gt;&lt;br /&gt;The way my micro allocator works is that you give it an initial estimate of memory usage for micro-allocations.  In a large game project, it might be good to give it a megabyte or two.  In fact, it is ideal if you give it the maximum amount of memory your application will ever use for micro-allocations.  You can find this out by running statistics on your application.  If you give it too conservative an estimate, then the performance of the micro-allocator will decrease significantly as it will begin allocating a lot of additional chunks and will need to search them for frees.&lt;br /&gt;&lt;br /&gt;If you are sure your application tends to use say 10 megabytes for micro-allocations, then give it that much to work with initially.&lt;br /&gt;&lt;br /&gt;The amount of memory reserve is equal to the default chunk size, times six.  As there are six powers of two from 8 to 256.&lt;br /&gt;&lt;br /&gt;It then creates six fixed pool allocators for all of the power of two multiples from 8 to 256 bytes.  It will do only one original heap allocation for this initial buffer and divvy up the memory usage equally between the six buffer sizes.  This initial heap is how it can quickly know whether or not an address is owned by the micro-allocator and in which fixed pool it belongs in.&lt;br /&gt;&lt;br /&gt;If you exceed this initial size, that is fine, the pools will simply grow based on your initial chunk size passed in.&lt;br /&gt;&lt;br /&gt;For the vast majority of the time an allocation simply returns the current free pointer.  A free simply patches the free list pointer as well.&lt;br /&gt;&lt;br /&gt;This system is similar to the LOKI memory allocator but it does not use the STL or any other external libraries.  It is also thread safe.&lt;br /&gt;&lt;br /&gt;Here is the source code.  Feedback welcome.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/MicroAllocator.h"&gt;MicroAllocator.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/MicroAllocator.cpp"&gt;MicroAllocator.cpp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can also get the source from here on &lt;a href="http://code.google.com/p/microallocator/"&gt;Google Code.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here are some hard statistics about the micro allocator.  First of all, I need to say that I am very impressed with the speed of the default allocator built into Microsoft Visual Studio's run-time.  It is very fast indeed.&lt;br /&gt;&lt;br /&gt;I created a stress test which adds ten million small objects to an STL list, iterates that list, and then deconstructs the list.  The way the STL implements lists each object causes a memory allocation to occur.&lt;br /&gt;&lt;br /&gt;In release build (outside of the debugger) here are the results. (It is important to note that memory allocations (either debug or release) are much slower if the Visual Studio debugger is present.  This is using STLPort.  The first number is using malloc/free the second number is using the micro allocator.&lt;br /&gt;&lt;br /&gt;Construction:           579 milliseconds to 422 milliseconds.&lt;br /&gt;Iteration:                    44 milliseconds to   44 milliseconds&lt;br /&gt;Deconstruction        431 milliseconds to  154 milliseconds&lt;br /&gt;&lt;br /&gt;As you can see allocation time was about 30% faster.  Iteration was the same.  Deconstruction time was 300% faster!&lt;br /&gt;&lt;br /&gt;Here is another piece of information showing the difference between the STL provided with Microsoft Visual Studio and STLPort.  The version of STLPort which is  being tested has exception handling and thread safety disabled.&lt;br /&gt;&lt;br /&gt;Construction STD::  676 milliseconds to STLPort 567 milliseconds&lt;br /&gt;Iteration                      62 milliseconds to STLPort  44 milliseconds&lt;br /&gt;Deconstruction STD 451 milliseconds to STLPort 402 milliseconds&lt;br /&gt;&lt;br /&gt;As you can see STLPort is just slightly faster than the STL which comes with Microsoft Visual Studio 2005.  However, the difference could simply be accounted for by the fact that thread safety and exception handling were disabled on this build of STLPort.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-3367399285049996187?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/microallocator/' title='A free open source micro allocator in C++'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/3367399285049996187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=3367399285049996187' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3367399285049996187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3367399285049996187'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/09/free-open-source-micro-allocator-in-c.html' title='A free open source micro allocator in C++'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_PtTKwwh_xBc/SqQFiklmi5I/AAAAAAAAGhE/21_i_8Gsgwg/s72-c/yX6zGzbltr05hzkrRsvBjbUdo1_500.jpg' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-6476120652503317373</id><published>2009-08-14T17:46:00.000-07:00</published><updated>2009-08-14T17:52:35.936-07:00</updated><title type='text'>Mesh Import Mesh Converter</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_PtTKwwh_xBc/SoYFqS7sX6I/AAAAAAAAGgc/9e5CFgZwNtE/s1600-h/gimpy.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 266px;" src="http://2.bp.blogspot.com/_PtTKwwh_xBc/SoYFqS7sX6I/AAAAAAAAGgc/9e5CFgZwNtE/s400/gimpy.jpg" alt="" id="BLOGGER_PHOTO_ID_5369985829880749986" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I have just revised my MeshImport library on &lt;a href="http://code.google.com/p/meshimport/"&gt;Google Code.&lt;/a&gt;  It's worth syncing to and checking it out.&lt;br /&gt;&lt;br /&gt;There is a tool in the subdirectory \bin\win32 called MeshConvert.exe which will convert to and from a variety of graphics file formats. &lt;br /&gt;&lt;br /&gt;The formats supported are:&lt;br /&gt;&lt;br /&gt;Wavefront OBJ&lt;br /&gt;Unreal PSK : Full skeletal mesh and animation support.&lt;br /&gt;Ogre3d : Full skeletal mesh and animation support.&lt;br /&gt;EZ-MESH : My own 'easy' (i.e. human readable) XML format for animated skeletal meshes.&lt;br /&gt;FBX : The FBX format from AutoDesk.&lt;br /&gt;&lt;br /&gt;The FBX soluition will not build until you have installed the FBX SDK from AutoDesk.  I am not allowed to distribute that SDK.  Also, you can only import, but not export FBX files.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-6476120652503317373?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/meshimport/' title='Mesh Import Mesh Converter'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/6476120652503317373/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=6476120652503317373' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/6476120652503317373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/6476120652503317373'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/08/mesh-import-mesh-converter.html' title='Mesh Import Mesh Converter'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_PtTKwwh_xBc/SoYFqS7sX6I/AAAAAAAAGgc/9e5CFgZwNtE/s72-c/gimpy.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-8983995659369007799</id><published>2009-08-01T16:23:00.001-07:00</published><updated>2009-08-01T16:37:10.834-07:00</updated><title type='text'>VectorFont a code snippet to render a high quality vector font in any application (uses the Hershey Font)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PtTKwwh_xBc/SnTOjO5lMbI/AAAAAAAAGXs/FtLtF4pZPRM/s1600-h/vextorfont.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 313px;" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/SnTOjO5lMbI/AAAAAAAAGXs/FtLtF4pZPRM/s400/vextorfont.jpg" alt="" id="BLOGGER_PHOTO_ID_5365140160795455922" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Click on the above image to see an example string printed using the code snippet presented here.&lt;br /&gt;&lt;br /&gt;This submission is an extremely useful code snippet.  It consists of one header file and one CPP that can render a high quality 3d vector font.  You provide a callback interface to 'draw a line'.  You can use OpenGL, Direct3D, GDI, or any other API you might choose.  You merely have to implement that one callback 'drawLine' and you get a high quality vector font that you can render in 2d or 3d as you prefer.  The font used is called the &lt;a href="http://emergent.unpythonic.net/software/hershey"&gt;'Hershey Font'&lt;/a&gt; and is public domain in this format.&lt;br /&gt;&lt;br /&gt;The pure virtual interface is called "VectorFont".  It has just one method 'vprintf' to printf a string through the vector font printing routine.&lt;br /&gt;&lt;br /&gt;The first parameter is an *optional* 4x4 matrix that the data points will be transformed through.  If you do not provide a transform, then the string will always be printed relative to the origin and you can do any placement you want in your own callback method.&lt;br /&gt;&lt;br /&gt;If you want the font to appear in 3d, but always 'camera facing', then you can build a camera facing rotation transform from the origin of the text to the current eye position.  You can build this transform by using the &lt;a href="http://codesuppository.blogspot.com/2006/03/lookat-sim-dietrich.html"&gt;'lookAt&lt;/a&gt;' code snippet I published on this site in the past.&lt;br /&gt;&lt;br /&gt;The next parameter you pass is 'textScale'.  This simply scales the font to a particular size you might wish.  A default of 1 is fine to start with and you can size from there until the font fits your particular needs.  Since it is a vector font, it looks good at pretty much any scale.&lt;br /&gt;&lt;br /&gt;The next parameter is a bool called 'centered'.  If this bool is true, then the text will be centered around the position you passed in.&lt;br /&gt;&lt;br /&gt;The final parameters are simply a standard 'printf' style format string and optional additional arguments.&lt;br /&gt;&lt;br /&gt;This is a damned useful code snippet and I would appreciate a thank you from anyone who uses it.&lt;br /&gt;&lt;br /&gt;Here is the source:  &lt;a href="http://www.amillionpixels.us/VectorFont.h"&gt;VectorFont.h&lt;/a&gt;&lt;br /&gt;                                  &lt;a href="http://www.amillionpixels.us/VectorFont.cpp"&gt;VectorFont.cpp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;----------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// This code snippet allows you to render a high quality vector line font.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// The font it uses is called the 'Hershey Font' (search for it on Google).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// This font is completely public domain and you are free to use it in&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// your own applications.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// Here is how you use this code snippet.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// Step #1 : Create an instance of the VectorFont pure virtual interface.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// Step #2 : call 'vprintf' with the transform, scale, center flag, and text you wish to print.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// Step #3 : Dispatch individual line segments to your own rendering framework.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// Step #4 : Release the VectorFont class.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// Here is an example usage in C++&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// class MyLineDraw : public VectorFontInterfac&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//     public:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//      virtual void drawLine(float x1,float y1,float x2,float y2)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//      {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//        // Right here, in this callback, draw the line using your own line draw interface, OpenGL, D3D, or whatever works for you.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//      }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//    };&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//    MyLineDraw mld; // create an instance of our callback class to draw individual line segments.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//    VectorFont *vf = createVectorFont(&amp;amp;mld);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//    vf-&gt;vprintf(NULL,1,true,"This is a test of the emergency broadcasting system.");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//    releaseVectorFont(vf);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;class VectorFontInterface&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  virtual void drawLine(float x1,float y1,float x2,float y2) = 0;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;class VectorFont&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  virtual void vprintf(const float *transform, // an *optional* 4x4 matrix transform to apply to each point as the font is rendered.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                       float textScale,        // A scaling value to apply to the vertices of the font.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                       bool centered,          // True if you want the text centered relative to its 3space position, specified in the translation component of 'transform' or 0,0,0 if no transform provided.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                       const char *fmt,        // A printf style format string&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                       ...) = 0;               // Optional additional parameters based on the format spec.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;VectorFont * createVectorFont(VectorFontInterface *vf);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;void         releaseVectorFont(VectorFont *vf);&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-8983995659369007799?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/8983995659369007799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=8983995659369007799' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8983995659369007799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8983995659369007799'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/08/vectorfont-code-snippet-to-render-high.html' title='VectorFont a code snippet to render a high quality vector font in any application (uses the Hershey Font)'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/SnTOjO5lMbI/AAAAAAAAGXs/FtLtF4pZPRM/s72-c/vextorfont.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-583492725578373536</id><published>2009-07-08T12:06:00.000-07:00</published><updated>2009-07-08T12:18:07.764-07:00</updated><title type='text'>Polygon Triangulator - Ear Clipping Method</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PtTKwwh_xBc/SlTufydnZxI/AAAAAAAAGVg/hpDYty79cGo/s1600-h/Tree.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://1.bp.blogspot.com/_PtTKwwh_xBc/SlTufydnZxI/AAAAAAAAGVg/hpDYty79cGo/s400/Tree.jpg" alt="" id="BLOGGER_PHOTO_ID_5356168086739707666" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here's a very useful code snippet.  It performs polygon triangulation on a set of planer 2d or 3d data points.  It supports concave polygons but not polygons with holes.&lt;br /&gt;&lt;br /&gt;This implementation uses the standard ear clipping algorithm which decomposes the polygon into convex pieces.  The API is really straightforward and easy to use.&lt;br /&gt;&lt;br /&gt;First create an instantiation of the triangulator class:&lt;br /&gt;&lt;br /&gt;Triangulator *t = createTriangulator();&lt;br /&gt;&lt;br /&gt;Next, add the set of points which define the polygon contour.  You can add the points as either floats or doubles; internally is uses double precision.  If your polygon is 2d, just pass zero for the z component.&lt;br /&gt;&lt;br /&gt;Example: t-&gt;addPoint(x,y,z);&lt;br /&gt;&lt;br /&gt;To perform the triangulation itself you call:&lt;br /&gt;&lt;br /&gt;unsigned int tcount;&lt;br /&gt;unsigned int *indices = t-&gt;triangulate(tcount,epsilon);&lt;br /&gt;&lt;br /&gt;This will return the number of triangles produced (stored in tcount) and a pointer to the array of triangle indices in the form of (a1,b1,c2,  a2,b2,c2, a3,b3,c3, ....).&lt;br /&gt;&lt;br /&gt;The value 'epsilon' is a threshold that determines whether or not a line segment in the polygon is considered co-linear or not.  Since we are dealing with floating point numbers there can be inherent precision issues.  Internally the triangulator operates at double precision.&lt;br /&gt;&lt;br /&gt;If you want to retrieve the original data points, based on the index, you cal call 'getPoint'.&lt;br /&gt;&lt;br /&gt;The implementation computes the bounding box for the input polygon and selects the two longest sides to perform the 2d triangulation against.&lt;br /&gt;&lt;br /&gt;If you want to triangulate another polygon, just call 't-&gt;reset()' and start adding the new points.&lt;br /&gt;&lt;br /&gt;When you are done with the triangulator class call:  releaseTriangulator(t)&lt;br /&gt;&lt;br /&gt;This code snippet uses the 'PIMPLE' paradigm (pointer to implementation) which is my favorite pattern.&lt;br /&gt;&lt;br /&gt;The primary benefit of this code is that it is nicely packaged in snippet form.&lt;br /&gt;&lt;br /&gt;The header file is: &lt;a href="http://www.amillionpixels.us/Triangulator.h"&gt;Triangulator.h&lt;/a&gt;&lt;br /&gt;and the implementation in: &lt;a href="http://www.amillionpixels.us/Triangulator.cpp"&gt;Triangulator.cpp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Also, the FloatMath library has been revised to use this implementation internally.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.h"&gt;FloatMath.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.inl"&gt;FloatMath.inl&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.cpp"&gt;FloatMath.cpp&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-583492725578373536?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/583492725578373536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=583492725578373536' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/583492725578373536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/583492725578373536'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/07/polygon-triangulator-ear-clipping.html' title='Polygon Triangulator - Ear Clipping Method'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_PtTKwwh_xBc/SlTufydnZxI/AAAAAAAAGVg/hpDYty79cGo/s72-c/Tree.jpg' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-3399118644329681655</id><published>2009-06-13T08:10:00.001-07:00</published><updated>2009-06-13T08:30:31.992-07:00</updated><title type='text'>Apparently I'm not Charles Bloom</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PtTKwwh_xBc/SjPByOoOtWI/AAAAAAAAGTE/mnAceY49_CY/s1600-h/P6065581.JPG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/SjPByOoOtWI/AAAAAAAAGTE/mnAceY49_CY/s400/P6065581.JPG" alt="" id="BLOGGER_PHOTO_ID_5346830251283363170" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Yesterday I posted a rant out of frustration at a frequent number of emails I get from people on the Internet.  I often get asked questions by people, who from the content of their question, clearly don't know how to program in C++ hardly at all.  It's difficult to figure out how to respond to that sort of thing.&lt;br /&gt;&lt;br /&gt;Here's the deal.  I'm a nice guy.  It's not just a put on, or an act, or a pose, or anything like that.  I'm genuinely a nice person.  I really like to help people out, not just in programming, but in life in general.  I also really like to teach and I absolutely don't mind people asking me programming questions.&lt;br /&gt;&lt;br /&gt;All that said, there are certain types of questions, like those that indicate you don't know how to program at all, that completely leave me at a loss.&lt;br /&gt;&lt;br /&gt;After I posted my rant yesterday an Anonymous (yep you heard it, anonymous) person left a comment chastising me for being so rude and obnoxious to people who just wanted to learn from a professional software developer.&lt;br /&gt;&lt;br /&gt;Well, anonymous comments on my blog are yet another one of my pet peeves that often make me launch off on a rant.  Seriously, if you ever really want me to answer a question, don't leave an Anonymous comment!  Take a moment and enter an email address so I can respond to you directly.&lt;br /&gt;&lt;br /&gt;Nevertheless, the guy who left the comment was right.  It is inappropriate and out of character for me to curse out beginner programmers who simply want to learn something.&lt;br /&gt;&lt;br /&gt;I edited yesterday's post, removed the F-bombs and personal insults, but left the basic tone and content the same.   With this post I would like to apologize.  I do encourage people, even beginners, to learn from my code snippets.  To be frank, that is often whey I write them!  Especially 'FloatMath' which is an amazing repository for various and sundry math functions.&lt;br /&gt;&lt;br /&gt;So, feel free to ask me questions and I promise I won't be insulting.  However, if you are such a beginner that you can't understand some very basic and simple things about C++ programming, I have to be honest, there isn't much I can tell you until you bone up on your skills.  And, if that is the case, I will try to say so politely instead of going off on a rant.&lt;br /&gt;&lt;br /&gt;I like to rant, just like Charles Bloom does, but I don't like the repercussions.  The things I wrote on my blog yesterday I would never say to someone's face.  Thus the weird dichotomy of Internet communications.&lt;br /&gt;&lt;br /&gt;Once again I apologize to anyone who might have been offended by my post.  I genuinely want to help programmers, even beginner programmers, solve their problems.  My main motivation in this site, besides simply sharing useful code with developers who have shared useful code with me (such as Charles Bloom one of the most generous open source developers out there) is to educate.&lt;br /&gt;&lt;br /&gt;If you are disappointed that I backed off my rant, then I strongly recommend you subscribe to a news feed of &lt;a href="http://cbloomrants.blogspot.com/"&gt;Charles Bloom's website&lt;/a&gt; as I'm sure you will find your daily dose of rank ranting over there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-3399118644329681655?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/3399118644329681655/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=3399118644329681655' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3399118644329681655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3399118644329681655'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/06/apparently-im-not-charles-bloom.html' title='Apparently I&apos;m not Charles Bloom'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/SjPByOoOtWI/AAAAAAAAGTE/mnAceY49_CY/s72-c/P6065581.JPG' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-1108956351697221577</id><published>2009-06-12T15:32:00.001-07:00</published><updated>2009-06-13T08:10:02.348-07:00</updated><title type='text'>Holy Crap???  My very own Charles Bloomesque Rant</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PtTKwwh_xBc/SjLXoA-_pTI/AAAAAAAAGS8/x4rDNZ0rKd0/s1600-h/dumb+and+dumber.jpg"&gt;&lt;img style="cursor: pointer; width: 293px; height: 400px;" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/SjLXoA-_pTI/AAAAAAAAGS8/x4rDNZ0rKd0/s400/dumb+and+dumber.jpg" alt="" id="BLOGGER_PHOTO_ID_5346572790101157170" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;( The snippet form of the best fit plane code can be found here.  It supports both single and double precision floating point numbers and even has an example 'main' in it for the truly technically challenged)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/bestfit.h"&gt;&lt;span style="font-style: italic;"&gt;bestfit.h&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;a href="http://www.amillionpixels.us/bestfit.cpp"&gt;bestfit.cpp&lt;/a&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(Note: The following rant has been edited from it's original by the author.)&lt;br /&gt;&lt;br /&gt;Holy crap.  I pride myself on being able to provide source code which is extremely (and I mean *extremely*) easy for people to adopt and use.&lt;br /&gt;&lt;br /&gt;That is why I put everything in 'snippet' form; and by that I mean one header, one CPP, with no external dependencies of any kind.  I provide code that is not dependent on special templates or data types.&lt;br /&gt;&lt;br /&gt;The one piece of code that people come to this site for a lot, is the code snippet I provided for computing a best fit plane.&lt;br /&gt;&lt;br /&gt;Now, I didn't even actually write this code myself.  &lt;a href="http://www.geometrictools.com/"&gt;David Eberly&lt;/a&gt; did on his Magic Software site.  I love David Eberly to death, he provides more amazing free source code to the community than nearly anyone else.  That said, David does commit the horrific crime of providing code that can *only* be used within the context of his personal suite of template/type libraries.  It is virtually impossible to just extract one useful math routine out of his code base without having to adopt every vector, matrix, quaternion, template, and every other dependency all of his code requires.&lt;br /&gt;&lt;br /&gt;In fact it took me the better part of the day to convert his 'best fit plane' routine into code snippet form.&lt;br /&gt;&lt;br /&gt;Now, it simply amazes me how many questions I get from people who can't understand how to use my code-snippet version!??!&lt;br /&gt;&lt;br /&gt;I have even had a number of people email me with the question "I don't get it, where is 'main'?".&lt;br /&gt;&lt;br /&gt;Really?  Seriously?&lt;br /&gt;&lt;br /&gt;This is one tiny isolated routine, one snippet of code.  Drop it into your own program, call it, and be done.&lt;br /&gt;&lt;br /&gt;If you don't know how to even use a code snippet in the first place, you might not be at the right web site...&lt;br /&gt;&lt;br /&gt;So, hey, maybe I'm wrong here.....&lt;br /&gt;&lt;br /&gt;So let's check back.&lt;br /&gt;&lt;br /&gt;Here is the only thing the header file contains for the best fit plane code snippet:&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;bool  fm_computeBestFitPlane(size_t vcount,     // number of input data points&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                     const float *points,     // starting address of points array.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                     size_t vstride,    // stride between input points.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                     const float *weights,    // *optional point weighting values.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                     size_t wstride,    // weight stride for each vertex.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                     float plane[4]);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;-----------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;So...what's the problem?  What is there not to understand?  I can understand not understaning the 'weighting' part, because I didn't really explain that.  But, the rest, really!???&lt;br /&gt;&lt;br /&gt;Ok, now in baby steps.....&lt;br /&gt;&lt;br /&gt;Let's say you have a set of 3D data points.  Woops....just realized I might be talking past my audience.&lt;br /&gt;&lt;br /&gt;3D means 'three dimensional' as in representing a location in three dimensional space, typically represented as the notation X, Y, and Z.&lt;br /&gt;&lt;br /&gt;Each point in space is three floating points numbers.&lt;br /&gt;&lt;br /&gt;Example:  float this_is_a_point_in_space[3] = { 3, 4, 5 };&lt;br /&gt;&lt;br /&gt;Got that?&lt;br /&gt;&lt;br /&gt;Understand?&lt;br /&gt;&lt;br /&gt;Ok, now let's represent 2 points in space.....&lt;br /&gt;&lt;br /&gt;float this_is_two_points_in_space[6] = { 3, 4, 5,    8, 1, 4 };&lt;br /&gt;&lt;br /&gt;Now, lots of people don't use just a float array to represent their points.  They often use data structures.&lt;br /&gt;&lt;br /&gt;They might have a structure like:&lt;br /&gt;&lt;br /&gt;struct Point&lt;br /&gt;{&lt;br /&gt;float x;&lt;br /&gt;float y;&lt;br /&gt;float z;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Thus, they might represent two ponts as:&lt;br /&gt;&lt;br /&gt;Point this_is_two_points[2];&lt;br /&gt;&lt;br /&gt;Get it? Follow me?&lt;br /&gt;&lt;br /&gt;And...sometimes...people have structures that contain data in addition to just the points!&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;br /&gt;struct Vertex&lt;br /&gt;{&lt;br /&gt;Point position;&lt;br /&gt;int     color;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Follow me?&lt;br /&gt;&lt;br /&gt;You can represent your points in a variety of ways *in your code* but one thing is always common.  A point, in 3 space, is three floating point numbers in the order of X, Y, Z.&lt;br /&gt;&lt;br /&gt;Thus... in my routine, you pass the address of the x component of your first point and the stride (stride is the distance between the first X and the next X in bytes).&lt;br /&gt;&lt;br /&gt;The return value is a plane.  What do I mean by that?&lt;br /&gt;&lt;br /&gt;There are four components to a plane equation typically expressed as A,B,C, and D.&lt;br /&gt;&lt;br /&gt;Now, my routine returns the results of the plane equation as four floating point numbers representing A,B,C, and D.&lt;br /&gt;&lt;br /&gt;What follows are several examples of how you can call my mysterious and cryptic code:&lt;br /&gt;&lt;br /&gt;--------------------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;float points[9] = { 3, 4, 2,  8, 1, 4, -4, 4, 3 }; // float array with 3 data points in the form of x,y,z&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;float plane[4]; // will contain the computed plane equation result&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;fm_computeBestFitPlane(3,  // we have 3 data points.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           points,       // the address of the X component of the first data point.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;           sizeof(float)*3,  // The stride (distance in bytes) between one point and the next.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          NULL,  // pass a null pointer for weights&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         0,           // pass a zero for weight stride.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       plane); // the address of the plane equation to store the result.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;-------------------------------------------------&lt;br /&gt;&lt;br /&gt;Ok, now here is an example presuming your code has data types such as 'Vertex' and 'Plane'.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Vertex vertices[3];&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Plane p;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;fm_computeBestFitPlane(number_of_points,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                                              &amp;amp;mVertices.mPoint.x,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                                              sizeof(Vertex),&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                                              0,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                                              0,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                                              &amp;amp;p.A); // the address to store the plane equation results in the form A,B,C,D&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;-------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;On a final note, the field for weights is an optional set of weighting values corresponding with each vertex.  They are unitless and simply serve as relative weighting components.&lt;br /&gt;&lt;br /&gt;If you want the plane fitting code to weigh some vertices more strongly than others, then you would pass a larger weight value at that index location.&lt;br /&gt;&lt;br /&gt;Since the weighting thing is entirely optional I won't bother to explain it further.  Personally, I think it is self-evident.&lt;br /&gt;&lt;br /&gt;Look, to adopt a number of these code snippets requires a minimum technical knowledge about programming in C++&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-1108956351697221577?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/1108956351697221577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=1108956351697221577' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1108956351697221577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1108956351697221577'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/06/holy-crap-my-veyr-own-charles.html' title='Holy Crap???  My very own Charles Bloomesque Rant'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/SjLXoA-_pTI/AAAAAAAAGS8/x4rDNZ0rKd0/s72-c/dumb+and+dumber.jpg' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-3577839025462045959</id><published>2009-05-22T11:22:00.000-07:00</published><updated>2009-05-22T11:38:07.196-07:00</updated><title type='text'>Telnet  : A code snippet that embeds a telnet client or server into your application</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PtTKwwh_xBc/ShbuH6P0u-I/AAAAAAAAGSc/jnT3cDKblGE/s1600-h/n807385115_532515_9764.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 301px;" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/ShbuH6P0u-I/AAAAAAAAGSc/jnT3cDKblGE/s400/n807385115_532515_9764.jpg" alt="" id="BLOGGER_PHOTO_ID_5338716227956423650" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This might well be the single most useful code snippet I have ever published.  I took some old code that was originally written as part of Novodex Rocket, later to become PhysX Rocket, and re-packaged it into snippet form.  This code was largely written by my friend &lt;a href="http://www.jamesdolan.com/"&gt;James Dolan&lt;/a&gt;, though some of it is mine as well.  Back when I was at Ageia we open-sourced the Rocket application and this code was part of that release.&lt;br /&gt;&lt;br /&gt;The only thing keeping this snippet from being widely useful is that, currently, it only builds on Windows or XBOX machines.  I have not yet ported it to Linux, Apple, Iphone,  etc.  It would be extremely useful on those platforms.  If anyone wants to volunteer to revise the code so that it conditionally compiles for those targets I would greatly appreciate it!&lt;br /&gt;&lt;br /&gt;What this code snippet does is that it allows you to embed a telnet server, or client, into any application.  Simply include the source into your project (telnet.cpp and telnet.h).&lt;br /&gt;&lt;br /&gt;Somewhere on startup in your code call:&lt;br /&gt;&lt;br /&gt;TELNET::createTelnet("localhost",23)&lt;br /&gt;&lt;br /&gt;This will create an instance of the telnet client/server system.  The first time you start it up on your machine, it should find port 23 free, and it will be created as a server.  The second time you launch it, it will see that port 23 is used, and instead it will launch as a client.   You can launch as many clients as you want and, of course, they don't have to be on the same machines.&lt;br /&gt;&lt;br /&gt;You can also just use an ordinary telnet client of any flavor and connect to your application.&lt;br /&gt;&lt;br /&gt;So, what is this good for?   It allows you to send debug commands and receive log spew from any application, without having to write any GUI interfaces.  This is especially useful for console games or anything running on an embedded system.  Think of it as a 'back door' way to poke commands into a running application and receive debug spew back out again.&lt;br /&gt;&lt;br /&gt;You can also use it as a quick and dirty way to do network communication.&lt;br /&gt;&lt;br /&gt;The code itself could be a little cleaner but, hey, it works.  I took what was previously about a dozen source files and combined them into one single large CPP file of roughly 2,000 lines in length.&lt;br /&gt;&lt;br /&gt;However, that is all about implementation and what you care about is the interface.&lt;br /&gt;&lt;br /&gt;Below is the entire header file for the telnet system.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;namespace TELNET&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;class Telnet&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  virtual bool          isServer(void) = 0; // returns true if we are a server or a client.  First one created on a machine is a server, additional copies are clients.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;  virtual bool          haveConnection(void) = 0; // returns true if we (as a client) successfully connected to the server.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;  virtual bool          sendMessage(unsigned int client,const char *fmt,...) = 0; // send a message to the server, all clients (client=0) or just a specific client.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;  virtual const char *  receiveMessage(unsigned int &amp;amp;client) = 0; // receive an incoming message (client=0) means it came from the server, otherwise it designates a specific client.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;  virtual const char ** getArgs(const char *input,int &amp;amp;argc) = 0; // parse string into a series of arguments.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;protected:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    virtual ~Telnet(void) { };&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Telnet * createTelnet(const char *address="LOCALHOST",unsigned int port=23);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;void     releaseTelnet(Telnet *t);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;extern TELNET::Telnet *gTelnet; // optional global variable representing the TELNET singleton for the application.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You can download the source directly from this location:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/telnet.h"&gt;telnet.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/telnet.cpp"&gt;telnet.cpp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Or, I recommend you sync to the &lt;a href="http://code.google.com/p/telnet/"&gt;Google code repository&lt;/a&gt; as it is guaranteed to always be the most current.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-3577839025462045959?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/telnet/' title='Telnet  : A code snippet that embeds a telnet client or server into your application'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/3577839025462045959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=3577839025462045959' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3577839025462045959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3577839025462045959'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/05/telnet-code-snippet-that-embeds-telnet.html' title='Telnet  : A code snippet that embeds a telnet client or server into your application'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/ShbuH6P0u-I/AAAAAAAAGSc/jnT3cDKblGE/s72-c/n807385115_532515_9764.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-6539627036268192310</id><published>2009-05-01T18:45:00.001-07:00</published><updated>2009-05-01T18:50:14.074-07:00</updated><title type='text'>More commentary about multiplatform development for mobile devices; including Iphone</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PtTKwwh_xBc/Sful6tI5B7I/AAAAAAAAGOc/ZJdUbv8nVUw/s1600-h/IsoRooms1.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 229px;" src="http://1.bp.blogspot.com/_PtTKwwh_xBc/Sful6tI5B7I/AAAAAAAAGOc/ZJdUbv8nVUw/s400/IsoRooms1.png" alt="" id="BLOGGER_PHOTO_ID_5331037011890997170" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I received the following emails from developer Benjamin Lee who confirmed that my strategy of doing multiplatform development by using Visual Studio on the PC was a good approach.&lt;br /&gt;&lt;br /&gt;&lt;div id=":3na" class="ii gt"&gt;         &lt;div link="blue" vlink="purple" lang="EN-US"&gt;  &lt;div&gt;  &lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;John,&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;I stumbled across your blog. Kudos for you for doing your dev on the PC. We actually do the same here. Our SDK runs on PC, Mac, and the iPhone. It runs nearly identical on all platforms, using the same datasets too. Aside from the obvious input differences, the only other differences we occasionally find are render issues, since the PC may render scenes slightly differently.&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;If your stuff already works well with the iPhone, then being able to have pretty stable Mac running code would be no problem. We could probably do the same with the Mac, but I have one mactoppie and the screen size is way too small to get any effective work done.&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;Thanks posting an interesting blog.&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;Ben&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;  &lt;/div&gt;  &lt;/div&gt;   &lt;/div&gt;&lt;br /&gt;and a follow up:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;John,&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And as you mentioned in your comment to anon on your "iphone development framework" post ... since you wanting to support more platforms, your method is really the way to go. To do otherwise is the long way around.&lt;br /&gt;&lt;br /&gt;We developed the PC SDK first. Then ported to Mac. Then ported to iPhone. The iPhone port took less than a day. We will probably port to the Wii next. But I expect that port to be very quick.&lt;br /&gt;&lt;br /&gt;You could also cite that other advantages are that you can do much better memory leak testing on the PC. While Instruments can be used (and we do test up against it), the PC provides a much better environment for memory counting (at least for us since like you, we were not Mac or iPhone people).&lt;br /&gt;&lt;br /&gt;Ben&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-6539627036268192310?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/6539627036268192310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=6539627036268192310' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/6539627036268192310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/6539627036268192310'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/05/more-commentary-about-multiplatform.html' title='More commentary about multiplatform development for mobile devices; including Iphone'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_PtTKwwh_xBc/Sful6tI5B7I/AAAAAAAAGOc/ZJdUbv8nVUw/s72-c/IsoRooms1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-105214352923530627</id><published>2009-04-25T13:21:00.001-07:00</published><updated>2009-04-25T13:30:57.368-07:00</updated><title type='text'>Iphone development framework</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PtTKwwh_xBc/SfNxAMAC5PI/AAAAAAAAGOM/7j5IR3iYuT4/s1600-h/119197856_fbc73ae2c7.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 266px;" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/SfNxAMAC5PI/AAAAAAAAGOM/7j5IR3iYuT4/s400/119197856_fbc73ae2c7.jpg" alt="" id="BLOGGER_PHOTO_ID_5328727032144782578" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is a follow up to my last post.  This past week I did, in fact, create a little framework that let's me develop for the Iphone primarily using Visual Studio under windows.  The process went very smoothly and the only difficulty, besides learning the Macintosh and Xcode, was that it was the first time I have programmed OpenGL.&lt;br /&gt;&lt;br /&gt;This framework is really just a starting point.  It has kind of a minimal implementation I needed to get my isometric game level to show up on the screen.&lt;br /&gt;&lt;br /&gt;Obviously I cannot make my game open source, since somebody would just steal it and upload it as their own to the App store, but I do plan to make the framework itself open source.  If I can get more developers to contribute to it, then it could become something quite useful.&lt;br /&gt;&lt;br /&gt;Even if no one else bothers to contribute to it, I am still proud to release it as a proof that this is a valid approach to developing for the Iphone.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://code.google.com/p/isogame-iphone/"&gt;Google Code location is here.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you are comfortable with SVN, you can just sync anonymously to this repository:&lt;br /&gt;&lt;br /&gt;&lt;tt id="checkoutcmd"&gt;&lt;strong&gt;&lt;em&gt;http&lt;/em&gt;&lt;/strong&gt;://isogame-iphone.googlecode.com/svn/trunk/&lt;br /&gt;&lt;br /&gt;If you aren't in to the whole SVN thing, you can just download the directory all zipped up from this location.&lt;br /&gt;&lt;br /&gt;http://code.google.com/p/isogame-iphone/downloads/list&lt;br /&gt;&lt;br /&gt;To check it out, under Windows, go to the compiler/vc8 directory and load 'WorldViewer.sln'&lt;br /&gt;&lt;br /&gt;It should build fine, if you are using 2008, just let it autoconvert the solution and project files.  Also you can disable any hooks to source control that might pop up.&lt;br /&gt;&lt;br /&gt;Once you build and run the project, hit '1' through '4' on the keyboard to load several test isometric game levels.&lt;br /&gt;&lt;br /&gt;Use 'W', 'A', 'S', 'D', to scroll around the map and the SPACEBAR will toggle between landscape and portrait.&lt;br /&gt;&lt;br /&gt;Meanwhile, on your Macintosh, just go to the directory /app/WorldViewer and load the Xcode project located there.&lt;br /&gt;&lt;br /&gt;Build and run it on your simulator and you will see the same exact application, using all of the same source code, running.&lt;br /&gt;&lt;br /&gt;The bulk of the interface that comprises the framework is in two header files.&lt;br /&gt;&lt;br /&gt;/include/IphoneGraphics/IphoneGraphics.h&lt;br /&gt;/include/IphoneGame/IphoneGame.h&lt;br /&gt;&lt;br /&gt;The single location that the Iphone or Windows app talks to the framework is exclusively through the pure virtual interface defined in 'IphoneGame.h'&lt;br /&gt;&lt;br /&gt;This framework is far from complete, it is only provided here as a 'proof of concept'.  If you are interested in using this framework as a starting point for a project and you intend to improve it, let me know and I will see about adding your as a member of the Google Code project.&lt;br /&gt;&lt;br /&gt;&lt;/tt&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-105214352923530627?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/isogame-iphone/' title='Iphone development framework'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/105214352923530627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=105214352923530627' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/105214352923530627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/105214352923530627'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/04/iphone-development-framework.html' title='Iphone development framework'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/SfNxAMAC5PI/AAAAAAAAGOM/7j5IR3iYuT4/s72-c/119197856_fbc73ae2c7.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-3352612896078957183</id><published>2009-04-20T10:19:00.000-07:00</published><updated>2009-04-20T10:27:50.768-07:00</updated><title type='text'>I need a game level designer</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_PtTKwwh_xBc/Seyvxi9SW0I/AAAAAAAAGOE/hGttsZn2PKA/s1600-h/zelda.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 301px;" src="http://3.bp.blogspot.com/_PtTKwwh_xBc/Seyvxi9SW0I/AAAAAAAAGOE/hGttsZn2PKA/s400/zelda.jpg" alt="" id="BLOGGER_PHOTO_ID_5326825725004766018" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Does anyone know of a young person who would enjoy doing some game level design for fun?  I am starting work on the Iphone and I plan to specialize in 2d isometric scrolling games.  I am using the level design tool called '&lt;a href="http://www.inet2inet.com/InetSoftware/World-Creator/WCv2/NewFeatures_Form.asp"&gt;World Creator 2.5&lt;/a&gt;' to create my game levels.&lt;br /&gt;&lt;br /&gt;If you know of a young person interested in getting a chance to work on a real game, for experience and to improve their resume, please let me know.  A familiarity with World Creator 2.5 is a major, major, plus.&lt;br /&gt;&lt;br /&gt;Please &lt;a href="mailto:jratcliffscarab@gmail.com"&gt;email me&lt;/a&gt; if you are interested in the opportunity.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-3352612896078957183?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/3352612896078957183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=3352612896078957183' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3352612896078957183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3352612896078957183'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/04/i-need-game-level-designer.html' title='I need a game level designer'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_PtTKwwh_xBc/Seyvxi9SW0I/AAAAAAAAGOE/hGttsZn2PKA/s72-c/zelda.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-1998434779996001436</id><published>2009-04-20T08:47:00.001-07:00</published><updated>2009-04-20T09:00:51.998-07:00</updated><title type='text'>Am I the only one developing their Iphone apps on the PC?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PtTKwwh_xBc/SeyZtdbRLhI/AAAAAAAAGN8/W3xpP-PMiRI/s1600-h/iphone.jpg"&gt;&lt;img style="cursor: pointer; width: 252px; height: 400px;" src="http://1.bp.blogspot.com/_PtTKwwh_xBc/SeyZtdbRLhI/AAAAAAAAGN8/W3xpP-PMiRI/s400/iphone.jpg" alt="" id="BLOGGER_PHOTO_ID_5326801465544617490" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So, I have only just started programming for the Iphone.  I got my MacMini and set it up.  I loaded and built a bunch of sample applications and got myself familiar with the development environment. &lt;br /&gt;&lt;br /&gt;I'm not really here to say anything all that critical about Xcode or the Iphone development system in particular.  The point here is one of familiarity.  I'm pretty old school, I mean really, really, old school.  Even though I am on Windows XP developing graphics based applications using Visual Studio, I still spend the vast majority of my day in a DOS command prompt running an ancient text editor, called &lt;a href="http://www.semware.com/"&gt;Qedit&lt;/a&gt;, that I have been using for over twenty years.&lt;br /&gt;&lt;br /&gt;The bottom line is that I am set in my ways, and I see no compelling reason to switch to a new development environment that I am unfamilar with.  Where are my macros, hot keys, batch files, etc. etc. ?&lt;br /&gt;&lt;br /&gt;So, the very first thing I decided to do when I started programming the Iphone was to write the bulk of the game using C++ and OpenGL on my PC.; with just a tiny bit of conditional compilation, I can run the same code on both systems.&lt;br /&gt;&lt;br /&gt;In addition to getting fast iteration cycles and being able to use tools I am familar with, there are some other advantages.&lt;br /&gt;&lt;br /&gt;The Iphone game I am working on is going to take advantage of the Blue-Tooth mulitplayer game features that will come out in OS3.0.  Dealing with all of the code to synchronize the game multiplayer is going to be quite complex, and I would hate to have to download a copy of the app to two different Iphone/Ipod touches just to test and debug it.&lt;br /&gt;&lt;br /&gt;On the PC I simply fire up two copies of the game, in two copies of visual studio.  I have the apps talk to each other using some kind of simple interprocess communication, and then I can debug all of the multiplayer code very rapidly.&lt;br /&gt;&lt;br /&gt;Could I do this on a Mac?  Maybe, but it would take me a long time to figure it out.&lt;br /&gt;&lt;br /&gt;This seems such a natural way to develop code, I'm suprised more people aren't doing it as well.  Isolate your OS specific code around some wrappers, write the entire application in C++ with just the absolute fewest minimal hooks from Objective C.&lt;br /&gt;&lt;br /&gt;Needless to say, I will be making this entire framework open source as it progresses, and I'm curious to see if anyone else finds it useful.&lt;br /&gt;&lt;br /&gt;Does this make sense to anyone else?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-1998434779996001436?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/1998434779996001436/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=1998434779996001436' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1998434779996001436'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1998434779996001436'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/04/am-i-only-one-developing-their-iphone.html' title='Am I the only one developing their Iphone apps on the PC?'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_PtTKwwh_xBc/SeyZtdbRLhI/AAAAAAAAGN8/W3xpP-PMiRI/s72-c/iphone.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-2174708613887775411</id><published>2009-04-18T16:10:00.001-07:00</published><updated>2009-12-13T12:13:45.413-08:00</updated><title type='text'>Texture Packing : A code snippet to compute a texture atlas</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PtTKwwh_xBc/SepeH0rEq6I/AAAAAAAAGN0/u7pQSDlDw_E/s1600-h/texture.png"&gt;&lt;img style="cursor: pointer; width: 293px; height: 400px;" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/SepeH0rEq6I/AAAAAAAAGN0/u7pQSDlDw_E/s400/texture.png" alt="" id="BLOGGER_PHOTO_ID_5326172997810432930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This source is now officially located on &lt;a href="http://code.google.com/p/texture-atlas/"&gt;Google Code here.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If I find time I will revise it to have a full sample application that loads a bunch of PNG/JPegs and packs them.&lt;br /&gt;&lt;br /&gt;------------------------&lt;br /&gt;&lt;br /&gt;I am providing a code snippet that computes a texture atlas.  This code snippet does not do any image processing, it merely figures out an efficient packing of rectangles into a single larger rectangle.  It is up to the user to copy the bitmaps themselves.&lt;br /&gt;&lt;br /&gt;One feature of the algorithm is that it will rotate source rectangles by 90 degrees if it makes them pack more efficiently.  Because of this you will need to be prepared to rotate your source U/V co-ordinates to account for this.&lt;br /&gt;&lt;br /&gt;This code snippet will optionally return an enclosing rectangle that is a power of two multiple.  Also it will, optionally, add a one pixel border around each texture if specified.&lt;br /&gt;&lt;br /&gt;I wrote this code snippets so that I can combine a bunch of tiled textures into a single texture for an Iphone game I am working on.  It seems to work, but I have no guarantees that it is optimal or robust.  If you use it, and improve it, please let me know.&lt;br /&gt;&lt;br /&gt;Here is how you use it.  Simply include the header file 'TexturePacker.h' and add the source file 'TexturePacker.cpp' to your project.  This code has no external dependencies.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/TexturePacker.h"&gt;TexturePacker.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/TexturePacker.cpp"&gt;TexturePacker.cpp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;First create an instance of the TexturePacker interface.&lt;br /&gt;&lt;br /&gt;TEXTURE_PACKER::TexturePacker *tp = TEXTURE_PACKER::createTexturePacker();&lt;br /&gt;//&lt;br /&gt;// Next inform the system how many textures you want to pack.&lt;br /&gt;//&lt;br /&gt;tp-&gt;setTextureCount(10);&lt;br /&gt;//&lt;br /&gt;// Now, add each texture's width and height in sequence 1-10&lt;br /&gt;//&lt;br /&gt;tp-&gt;addTexture(wid,hit)&lt;br /&gt;//&lt;br /&gt;// Next you pack them .&lt;br /&gt;//&lt;br /&gt;int unused_area = tp-&gt;packTextures(width,height,true,true)&lt;br /&gt;//&lt;br /&gt;The return code is the unused surface area.  It also returns the width and height of the rectangle needed to contain all textures.&lt;br /&gt;&lt;br /&gt;If you want to force your output texture to be a power of two, set that option to true.&lt;br /&gt;If you want a one pixel border around your textures set that parameter to true.&lt;br /&gt;&lt;br /&gt;Finally, to retrieve the results, for each texture 0-(n-1) call 'getTextureLocation'.&lt;br /&gt;&lt;br /&gt;This will return the x,y position of the texture in the texture atlas, and the width and height (should be the same as the original)&lt;br /&gt;&lt;br /&gt;Now, this is very important, if the call to getTextureLocation returns true, it means that the texture was rotated 90 degrees to make it better fit into the available space.  You should rotate your U/V co-ordinates accordingly.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The algorithm for packing textures as as follows:&lt;br /&gt;&lt;br /&gt;Step #1 : Find the longest edge and total area of all source textures.&lt;br /&gt;&lt;br /&gt;Step #2 : Create a single large rectangle big enough to fit all textures; round up to the nearest power of two if necessary.  Add this rectangle as a node in the 'free list'.&lt;br /&gt;&lt;br /&gt;Step #3 : Place each texture, first by finding the texture with the largest area and longest edge that has not yet been placed.&lt;br /&gt;&lt;br /&gt;Step #4 :  .. Look through the free nodes list, and if a free node is exactly the same size, then use it.&lt;br /&gt;              Otherwise, find a free node that is furthest down and to the left of the co-ordinate space (growing up and to the right while we stack)&lt;br /&gt;              Always insert the node so that the long edge lays down, preventing as much as possible the texture-atlas from growing vertically.&lt;br /&gt;              If a placed node has been rotated 90 degrees (width/height swapped) flag it as so.&lt;br /&gt;&lt;br /&gt;Step #5 : If the texture we are inserting shares an edge with the free node, then simply shrink the free node down to make up the difference.&lt;br /&gt;&lt;br /&gt;Step #6 : If the texture doesn't share any edge then split the rectangle in two, allocating a new free node and adding to the node list.&lt;br /&gt;&lt;br /&gt;Step #7 : See if any nodes can be combined back into one; do this until no more rectangles can be collapsed.&lt;br /&gt;&lt;br /&gt;Step #8 : Repeat until all textures have been inserted.&lt;br /&gt;&lt;br /&gt;Step #9 : Find the maximum height we ended up using and return that as the actual height. Clamp the height to the nearest power of two if needed.&lt;br /&gt;&lt;br /&gt;Step #10 : Iterate through the results and copy your textures to a single large texture-atlas.&lt;br /&gt;             This code does not do the image copying, that is done by your own application.&lt;br /&gt;&lt;br /&gt;If you use this snippet, and especially if you improve it, let me know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-2174708613887775411?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/texture-atlas/' title='Texture Packing : A code snippet to compute a texture atlas'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/2174708613887775411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=2174708613887775411' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2174708613887775411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2174708613887775411'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/04/texture-packing-code-snippet-to-compute.html' title='Texture Packing : A code snippet to compute a texture atlas'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/SepeH0rEq6I/AAAAAAAAGN0/u7pQSDlDw_E/s72-c/texture.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-4780857044257943223</id><published>2009-04-18T07:52:00.000-07:00</published><updated>2009-04-18T07:54:06.003-07:00</updated><title type='text'>Nvidia PhysX APEX Cloth Integration for GDC 09</title><content type='html'>&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/npb7BlM-8qg&amp;hl=en&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/npb7BlM-8qg&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Here is a video clip showing the APEX cloth integration I did for GDC09.  I currently work at Simutronics on the MMO game engine called HeroEngine.  My friends working on the PhysX SDK did a really cool clothing module and I was the first person who got a chance to integrate it into a game engine.  I think the results turned out pretty well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-4780857044257943223?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/4780857044257943223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=4780857044257943223' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/4780857044257943223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/4780857044257943223'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/04/nvidia-physx-apex-cloth-integration-for.html' title='Nvidia PhysX APEX Cloth Integration for GDC 09'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-7250289465025642425</id><published>2009-03-08T14:26:00.000-07:00</published><updated>2009-03-11T15:58:23.523-07:00</updated><title type='text'>Best Fit Plane : Best Fit AABB : Best Fit OBB : Best Fit Sphere : Best Fit Capsule</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_PtTKwwh_xBc/SbQ5JjbN8PI/AAAAAAAAGIg/CEZexIGF_Tw/s1600-h/%2Bclvg-P1160744.JPG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 347px;" src="http://2.bp.blogspot.com/_PtTKwwh_xBc/SbQ5JjbN8PI/AAAAAAAAGIg/CEZexIGF_Tw/s400/%2Bclvg-P1160744.JPG" alt="" id="BLOGGER_PHOTO_ID_5310932696867664114" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;(A concrete example of two best fit spheres.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Today I put together a code snippet that contains just my 'best fit' routines.  Probably the most common thing people come to this website for.  They have been isolated into a single CPP and header file inside the namespace 'BEST_FIT'.&lt;br /&gt;&lt;br /&gt;These are simply copies of the same routines which are found in the larger snippets collection called 'FloatMath'.&lt;br /&gt;&lt;br /&gt;There is one new function I haven't previously posted which is a best fit capsule routine.  The best fit capsule is derived by first computing the best fit OBB and then orienting the capsule along its longest edge and computing the radius by examining the maximum distance along the two shorter edges.&lt;br /&gt;&lt;br /&gt;The capsule returned is in the exact format used by the PhysX SDK; which assumes that the Y axis of the capsule represents 'height' and the X/Z plane is the radius.&lt;br /&gt;&lt;br /&gt;It is important to note that if the returned capsule height is a negative number, that means it could not be represented as a capsule and, instead, you should treat it as a sphere with the radius returned.  Also, intentionally, there is a chance some points of the input cloud could extend outside of the capped spheres at then ends of the capsule.  I did this on purpose because my primary use for the capsule fitting code is for automatic ragdoll generation and that kind of error is more than acceptable.  I doubt it would matter in most use cases, but you should be aware of the limitation.&lt;br /&gt;&lt;br /&gt;As in my previous source snippets, these routines should allow you to directly use your existing vector, matrix, and quaternion classes, unless they are particularily non-standard.&lt;br /&gt;&lt;br /&gt;A vector is assumed to be a float pointer representing X, Y, and Z&lt;br /&gt;A quaternioni is assumed to be a float 4 pointer to a quaternion in the format X, Y, Z, W&lt;br /&gt;A matrix is assumed to be a float 16 pointer to a 4x4 matrix in the traditional D3DX format.&lt;br /&gt;&lt;br /&gt;If you represent your quaternions or matrices differently, you will want to translate the results on the way in and out, otherwise you can just cast your existing classes to a float pointer and you should be able to use the routines directly.&lt;br /&gt;&lt;br /&gt;Here is a direct link to the BestFit source code snippet:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/BestFit.h"&gt;BestFit.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/BestFit.cpp"&gt;BestFit.cpp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here is a direct link to the latest version of the FloatMath code snippet library, which has grown somewhat large over time, but now includes some more powerful geometric primitives.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.h"&gt;FloatMath.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.cpp"&gt;FloatMath.cpp&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.inl"&gt;FloatMath.inl&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;------------ Important note as of March 11, 2009&lt;br /&gt;&lt;br /&gt;The best fit sphere routine has been updated to be exact, per Charles Bloom's recommendations.  I will update the OBB routine relatively soon, I'm going to try out Bloom's convex hull routine and see if it is appropriate as a pre-process stage for the OBB point cloud.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-7250289465025642425?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/7250289465025642425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=7250289465025642425' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/7250289465025642425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/7250289465025642425'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/03/best-fit-plane-best-fit-aabb-best-fit.html' title='Best Fit Plane : Best Fit AABB : Best Fit OBB : Best Fit Sphere : Best Fit Capsule'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_PtTKwwh_xBc/SbQ5JjbN8PI/AAAAAAAAGIg/CEZexIGF_Tw/s72-c/%2Bclvg-P1160744.JPG' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-2706065772378196346</id><published>2009-02-28T14:30:00.001-08:00</published><updated>2009-02-28T14:38:09.778-08:00</updated><title type='text'>FastXml : An extremely lightweight stream oriented XML parser</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_PtTKwwh_xBc/Sam7Yi4ws2I/AAAAAAAAGII/uHxZiYDomPc/s1600-h/launch.jpg"&gt;&lt;img style="cursor: pointer; width: 247px; height: 317px;" src="http://2.bp.blogspot.com/_PtTKwwh_xBc/Sam7Yi4ws2I/AAAAAAAAGII/uHxZiYDomPc/s400/launch.jpg" alt="" id="BLOGGER_PHOTO_ID_5307979666188972898" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In the past when I needed to parse an XML file I have been using TinyXML; which is a nice XML system and quite robust.  However, most of the time, when I want to parse an XML file I really just need to treat it as a raw stream of data and I don't need any support for parent/child relationships or other hierarchical information.&lt;br /&gt;&lt;br /&gt;And, while TinyXML is kind of tiny, it's still a fair amount of source code somewhere around 6,000 lines or so.  It also isn't particularly fast.&lt;br /&gt;&lt;br /&gt;Today I wrote an XML parser that is extremely non-robust.  It pretty much assumes perfectly formed XML data and I don't know if I have taken every single use case into account.  It does manage to parse all of my sample data that I needed, and, for me, that was enough.&lt;br /&gt;&lt;br /&gt;FastXml is only about 350 lines long and is very fast.  It parses 'in place' like my in-place parser and guarentees that all elements, text, and attributes are persistent pointers; something your application may be able to take advantage of.&lt;br /&gt;&lt;br /&gt;Here are links to the source code:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FastXml.h"&gt;FastXml.h&lt;/a&gt;&lt;a href="http://www.amillionpixels.us/FastXml.cpp"&gt;&lt;br /&gt;FastXml.cpp&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-2706065772378196346?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/2706065772378196346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=2706065772378196346' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2706065772378196346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2706065772378196346'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/02/fastxml-extremely-lightweight-stream.html' title='FastXml : An extremely lightweight stream oriented XML parser'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_PtTKwwh_xBc/Sam7Yi4ws2I/AAAAAAAAGII/uHxZiYDomPc/s72-c/launch.jpg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-2423572453264621665</id><published>2009-02-21T16:29:00.000-08:00</published><updated>2009-02-21T16:32:33.827-08:00</updated><title type='text'>Updated CodeSuppository</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PtTKwwh_xBc/SaCcwuAvHfI/AAAAAAAAGH4/GmpIBFtCeBU/s1600-h/1478016880_501bb883e9.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 278px;" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/SaCcwuAvHfI/AAAAAAAAGH4/GmpIBFtCeBU/s400/1478016880_501bb883e9.jpg" alt="" id="BLOGGER_PHOTO_ID_5305412721841217010" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I updated the CodeSuppository Repository on &lt;a href="http://code.google.com/p/codesuppository"&gt;Google Code today&lt;/a&gt;.  It includes a working version of the MeshImporter system and allows you to import meshes in a variety of formats and perform various geometric operations on them.&lt;br /&gt;&lt;br /&gt;I need to spend more time on documentation and such, but I just wanted to get the code current.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-2423572453264621665?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/codesuppository' title='Updated CodeSuppository'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/2423572453264621665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=2423572453264621665' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2423572453264621665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2423572453264621665'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/02/updated-codesuppository.html' title='Updated CodeSuppository'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/SaCcwuAvHfI/AAAAAAAAGH4/GmpIBFtCeBU/s72-c/1478016880_501bb883e9.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-521796364564283121</id><published>2009-01-10T13:33:00.001-08:00</published><updated>2009-01-10T14:15:34.181-08:00</updated><title type='text'>Intel's giant screw up with the Intel Threading Library TBB</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_PtTKwwh_xBc/SWkUP_4QrzI/AAAAAAAAGFQ/4aooO7NW5DU/s1600-h/alwaysopen.jpg"&gt;&lt;img style="cursor: pointer; width: 319px; height: 191px;" src="http://3.bp.blogspot.com/_PtTKwwh_xBc/SWkUP_4QrzI/AAAAAAAAGFQ/4aooO7NW5DU/s400/alwaysopen.jpg" alt="" id="BLOGGER_PHOTO_ID_5289781502401359666" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I got in a discussion on a forum about the Intel Threading Library and now that discussion turned into a &lt;a href="http://www.ogre3d.org/forums/viewtopic.php?f=16&amp;amp;t=46970&amp;amp;p=323261#p323261"&gt;rant&lt;/a&gt;.  I have now decided to cross post that &lt;a href="http://www.ogre3d.org/forums/viewtopic.php?f=16&amp;amp;t=46970&amp;amp;p=323261#p323261"&gt;rant &lt;/a&gt;here to my blog.  (I encourage you to read the &lt;a href="http://www.ogre3d.org/forums/viewtopic.php?f=16&amp;amp;t=46970&amp;amp;p=323261#p323261"&gt;entire thread of discussion&lt;/a&gt; on the Ogre3d forums, because there is a lot of interesting follow-up conversation. And, by the way, the purpose of this rant is to shame Intel into fixing their ridiculous licensing decision on a handful of header files.)&lt;br /&gt;&lt;br /&gt;A very legitimate question to me would be, John, why did you write the JobSwarm threading library when Intel already has an awesome open source threading library called &lt;a href="http://www.threadingbuildingblocks.org/"&gt;TBB&lt;/a&gt;?&lt;br /&gt;&lt;br /&gt;Yeah, good question.&lt;br /&gt;&lt;br /&gt;Here's the answer why......&lt;br /&gt;&lt;br /&gt;-------------------------&lt;br /&gt;&lt;br /&gt;&gt;&gt;This exception is actually very unrestrictive, in fact, that exception makes the licence of TBB less restrictive than LGPL. It is definitely usable in commercial applications and does not enforce GPL on your own code....&lt;br /&gt;&lt;br /&gt;We must not be reading the same thing.  According to the announcement, TBB is under GPL2.  On their site they refer to a commercial version and a commercially 'aligned' version whatever that is supposed to mean.  At the end of the day it is released under GPL.&lt;br /&gt;&lt;br /&gt;Please read the GPL license located here: &lt;a href="http://www.gnu.org/copyleft/gpl.html"&gt;http://www.gnu.org/copyleft/gpl.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It is a massive and dense document that would require an attorney to figure out.  Now, I'm not an attorney but, but let me tell you this, our attorneys tell us that under no circumstances can we use any GPL code in any way shape or form in any of our projects here at work. I don't care what little 'caveat' Intel shoved into their readme file so long as it has the word 'GPL' anywhere near it, I cannot touch it at my job period.&lt;br /&gt;&lt;br /&gt;Realize that all of the source I release is also used by me at my job.  I consult with my employer and we make selective decisions as to what code we will release open source and what we will not.  We release open source for a variety of reasons: generating good karma, generally being a nice guy, and hoping that we will benefit from improvements and bug fixes made by others, or from software created by others that incorporates our code.&lt;br /&gt;&lt;br /&gt;By comparison, here is the MIT license.  I don't need to provide a separate link because it is so short and sweet one is not needed.  It says the source is free, do with it as you will, and don't blame me if something goes wrong.  That, in my opinion, is the only license any true 'open source' project should be in.  It certainly should be no more than a paragraph or two, a couple of hundred words at best, and not a massive document such as GPL.&lt;br /&gt;&lt;br /&gt;By the way, I am not alone in my opinion on this topic.  Here is a link to a developer who says almost word for word the same thing I just said.  &lt;a href="http://www.linuxjournal.com/article/5935"&gt;http://www.linuxjournal.com/article/5935&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you can't tell by now, I’m really annoyed that Intel has this fantastic threading library that they ‘want everyone to use’ but then release it under GPL; a license that prevents virtually any commercial software developer from using it; based on company policy if nothing else.&lt;br /&gt;&lt;br /&gt;(WHAT IS EVEN WORSE IS THAT OPEN-SOURCE DEVELOPERS CAN'T USE IT EITHER!  BECAUSE GPL IS A VIRUS AND EVEN IF MY OPEN-SOURCE PROJECT IS MIT THE MOMENT I PUT GPL CODE INTO MY PROJECT IT IS NOW INFECTED WITH THIS DISGUSTING VIRAL MEME THUS MAKING MY PROJECT USELESS!!!)&lt;br /&gt;&lt;br /&gt;As I assume you know, it is corporate policy at virtually all companies that no GPL code can be used &lt;span style="font-weight: bold; font-style: italic;"&gt;period&lt;/span&gt;.  And, because of the damage GPL issues have raised, now many companies won’t allow any open source code of any kind, no matter what the license.  Which makes the job of a commercial software developer a giant pain in the ass when he has to completely rewrite open  source code just so that his company now ‘owns it’.&lt;br /&gt;&lt;br /&gt;I know of one major company in particular that I do consulting for that has this restriction.  I know from personal experience just how frustrating this can be.  Until Intel removes the phrase 'GPL license' from TBB it will never be adopted by virtually any commercial projects.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The MIT license:&lt;br /&gt;&lt;br /&gt;Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:&lt;br /&gt;&lt;br /&gt;The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;&lt;br /&gt;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-521796364564283121?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.ogre3d.org/forums/viewtopic.php?f=16&amp;t=46970&amp;p=323261#p323261' title='Intel&apos;s giant screw up with the Intel Threading Library TBB'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/521796364564283121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=521796364564283121' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/521796364564283121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/521796364564283121'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/01/intels-giant-screw-up-with-intel.html' title='Intel&apos;s giant screw up with the Intel Threading Library TBB'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_PtTKwwh_xBc/SWkUP_4QrzI/AAAAAAAAGFQ/4aooO7NW5DU/s72-c/alwaysopen.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-3124272789242068157</id><published>2009-01-10T12:59:00.001-08:00</published><updated>2009-01-10T16:34:53.149-08:00</updated><title type='text'>Code Suppository Respository to move to Google Code</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PtTKwwh_xBc/SWkNckImMTI/AAAAAAAAGFI/c9PUFDaUABU/s1600-h/302-fukitol.jpg"&gt;&lt;img style="cursor: pointer; width: 358px; height: 384px;" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/SWkNckImMTI/AAAAAAAAGFI/c9PUFDaUABU/s400/302-fukitol.jpg" alt="" id="BLOGGER_PHOTO_ID_5289774021710590258" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;IMPORTANT ANNOUNCEMENT AS OF JANUARY 10, 2009!!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;                                                                                                                    &lt;br /&gt;&lt;br /&gt;I will be leaving this page up, with the existing links for a while; perhaps another few months.  However, the&lt;a href="http://www.amillionpixels.us/sourcecode.htm"&gt; CodeSuppository Respository&lt;/a&gt; is officially moving to &lt;a href="http://code.google.com/"&gt;&lt;span style="text-decoration: underline;"&gt;Google Code&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I will be performing all of my open source development on Google code in the future and will, eventually, be removing all code from this particular page.&lt;br /&gt;&lt;br /&gt;The first three projects released on Google code are:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sourceforge.net/projects/jobswarm/"&gt;JobSwarm &lt;/a&gt;: A lightweight, lock-free, multithreaded job scheduling system (often called ‘microthreading)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sourceforge.net/projects/meshimport/"&gt;MeshImport &lt;/a&gt;: (Early alpha/design phase at this time) An open source plugin system designed to handle general purpose mesh data transfer between application components.  Supports meshes, skeletons, bone weightings, and animation data.  While similar to the &lt;a href="http://sourceforge.net/projects/assimp/"&gt;OpenAssetImport &lt;/a&gt;library, MeshImport has a separate DLL plugin for each importer, thus making it easy for developers to create custom importers for their own projects, and allowing you to keep some importers open source and others proprietary.  MeshImport is currently in early alpha, but will be getting a lot more support very soon.  Another important feature of the MeshImport system is that it does not assume the data resides on a physical file on disk (a bad assumption made by the OpenAssetImport library.)  One of the MeshImport plugins will, however, support the OpenAssetImport library to rapidly ramp up a lot of additional formats.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/codesuppository/"&gt;CodeSuppository&lt;/a&gt;: This will be the main location for the entirety of my complete collection of code snippets.  They will be wrapped in a DirectX9 interactive application framework so that you can visually see and demonstrate each of the individual features.  An initial release is now available which does, in fact, include almost all of the source for my various code snippets.  However, I have not yet had time to write specific demo implementations for each samples.  Those will come online as a I find time.  There are samples for a few of the most useful, and frequently referenced, snippets on this site.  Best Fit OBB, Best Fit Plane, and Convex Hull.&lt;br /&gt;&lt;br /&gt;If you want to be a contributing member to any of these projects, please send me an email to: jratcliffscarab@gmail.com.  Include your Google member name as well as information about yourself; website, qualifications as a developer, and interests.  In general I will be willing to allow trustworthy and competent developers contribute to these projects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-3124272789242068157?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/sourcecode.htm' title='Code Suppository Respository to move to Google Code'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/3124272789242068157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=3124272789242068157' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3124272789242068157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3124272789242068157'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/01/code-suppository-respository-to-move-to.html' title='Code Suppository Respository to move to Google Code'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/SWkNckImMTI/AAAAAAAAGFI/c9PUFDaUABU/s72-c/302-fukitol.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-2297977703661850025</id><published>2009-01-07T08:49:00.001-08:00</published><updated>2009-01-10T16:31:23.973-08:00</updated><title type='text'>CodeSuppository moving to Google Code</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PtTKwwh_xBc/SWTdWGKyx4I/AAAAAAAAGFA/11pUYFjthF8/s1600-h/751699198_5999cc6beb_o.jpg"&gt;&lt;img style="cursor: pointer; width: 267px; height: 400px;" src="http://1.bp.blogspot.com/_PtTKwwh_xBc/SWTdWGKyx4I/AAAAAAAAGFA/11pUYFjthF8/s400/751699198_5999cc6beb_o.jpg" alt="" id="BLOGGER_PHOTO_ID_5288595234122549122" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Over the coming weeks (months?) I will be moving all of my 'CodeSuppository' resources over to Google Code.  If you want to be a contributor to any project, just send me an email with your Google account along with a little information about you.&lt;br /&gt;&lt;br /&gt;So far, I have only moved the &lt;a href="http://code.google.com/p/jobswarm/"&gt;'JobSwarm' &lt;/a&gt;multithreading jobscheduler to Google code.  David Pangerl from the algorithms list took it upon himself to finish up the lock-free queue which now seems to be stable and working nicely.&lt;br /&gt;&lt;br /&gt;The next task needed for the JobSwarm code base is for someone to revise the source so it will build on Linux, which would be nice.&lt;br /&gt;&lt;br /&gt;Where is the JobSwarm project going in the future?  As I begin to use it more for 'real work' in my own personal project I expect there will be enhancements and/or new component layers.&lt;br /&gt;&lt;br /&gt;Things that might get added are:&lt;br /&gt;&lt;br /&gt; * Job batches&lt;br /&gt; * Job priorities&lt;br /&gt; * Job and Job batch dependencies&lt;br /&gt; * Inter-Job communication&lt;br /&gt; * A lock-free tiny memory allocator for individual job processing.&lt;br /&gt; * A message based system for managing the flow of control of job completion events.&lt;br /&gt;&lt;br /&gt;The JobSwarm project is currently located &lt;a href="http://code.google.com/p/jobswarm/"&gt;here on Google code&lt;/a&gt;  You can either sync directly to the source code using SVN or download the pre-built binary packages.&lt;br /&gt;&lt;br /&gt;SVN: &lt;tt&gt;svn checkout &lt;strong&gt;&lt;em&gt;http&lt;/em&gt;&lt;/strong&gt;://jobswarm.googlecode.com/svn/trunk/ jobswarm-read-only&lt;/tt&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-2297977703661850025?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/jobswarm/' title='CodeSuppository moving to Google Code'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/2297977703661850025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=2297977703661850025' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2297977703661850025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2297977703661850025'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/01/codesuppository-moving-to-sourceforge.html' title='CodeSuppository moving to Google Code'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_PtTKwwh_xBc/SWTdWGKyx4I/AAAAAAAAGFA/11pUYFjthF8/s72-c/751699198_5999cc6beb_o.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-8918545798368647470</id><published>2009-01-02T10:03:00.000-08:00</published><updated>2009-01-11T08:37:31.047-08:00</updated><title type='text'>JobSwarm : A microthreading framework with lockless FIFO</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PtTKwwh_xBc/SV5Xgj4BGhI/AAAAAAAAGE4/24nko97gXdM/s1600-h/swarm.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 320px;" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/SV5Xgj4BGhI/AAAAAAAAGE4/24nko97gXdM/s400/swarm.jpg" alt="" id="BLOGGER_PHOTO_ID_5286759229477165586" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(I'm trying to use Google Code for the first time.  You can try getting the code from there at this &lt;a href="http://code.google.com/p/jobswarm/"&gt;link&lt;/a&gt;&lt;a href="http://code.google.com/p/jobswarm/"&gt;.&lt;/a&gt;  Please &lt;a href="http://codesuppository.blogspot.com/2009/01/codesuppository-moving-to-sourceforge.html"&gt;read the latest post about JobSwarm &lt;/a&gt;on this site.)&lt;br /&gt;&lt;br /&gt;I used part of my Christmas break to implement a system that I have been wanting for a long time.  I call it a 'JobSwarm'.  What it is, is a micro-threading library that can handle tens of thousands of extremely tiny jobs with almost no overhead.&lt;br /&gt;&lt;br /&gt;In the sample program provided I compute a fractal by decomposing it into 65,536 individual jobs, each one representing 64 pixels of a 2kx2k image.&lt;br /&gt;&lt;br /&gt;The usage pattern for the JobSwarm is as follows.&lt;br /&gt;&lt;br /&gt;First, you create a JobSwarmContext.  This is a single instance of the JobSwarm system.  When you create a JobSwarmContext you tell it how many physical threads you want to use.  You can either create a single JobSwarmContext for your entire application, or you can create different ones in various subsystems.&lt;br /&gt;&lt;br /&gt;When a JobSwarmContext is released any currently executing jobs will have to be completed before the method can return.&lt;br /&gt;&lt;br /&gt;To use the JobSwarm you simply inherit the pure-virtual interface 'JobSwarmInterface' and implement three methods.&lt;br /&gt;&lt;br /&gt;They are:&lt;br /&gt;&lt;br /&gt;job_process&lt;br /&gt;job_onFinish&lt;br /&gt;job_onCancel&lt;br /&gt;&lt;br /&gt;You find this interface in the header file 'JobSwarm.h' and enclosed in the namespace 'JOB_SWARM'.&lt;br /&gt;&lt;br /&gt;A simple example of how to use this is in 'fractal.cpp' and in the class 'FractalJob'.&lt;br /&gt;&lt;br /&gt;The three methods are implemented as follows:&lt;br /&gt;&lt;br /&gt;job_process : This is the actual 'work' this job is supposed to do.  This code will operate in a seperate thread and, therefore, must be entirely thread safe.&lt;br /&gt;&lt;br /&gt;job_onFinish : This is a method which is called when your job has completed.  This method is invoked in the main thread (the thread which owns the JobSwarmContext).  This allows you to do anything with results you may have computed during the 'job_process' call.&lt;br /&gt;&lt;br /&gt;job_onCancel : This is a methd which is called when your job was cancelled.  This method is called from the main thread.&lt;br /&gt;&lt;br /&gt;To manage the job swarm you use the following methods on the JobSwarmContext.&lt;br /&gt;&lt;br /&gt;createSwarmJob : This creates a single job to be processed.&lt;br /&gt;&lt;br /&gt;cancel : This cancels a previously posted job.  It is very important to note that this only marks the job to be cancelled!  You cannot destruct the job until you recieve the 'job_onCancel' callback.&lt;br /&gt;&lt;br /&gt;processSwarmJobs : This is a 'pump' loop method which is called from the main thread.  This call allows completed and/or cancelled jobs to be despooled.  This is a very lightweight call but if you forget to invoke it none of your job completion events will ever occur.&lt;br /&gt;&lt;br /&gt;setUseThreads : By default the job swarm system runs using hardware threads.  However, for debugging and/or performance comparison tests, it can be toggled on and off on the fly.  Setting 'useThreads' to false does not close out the hardware threads themselves, it simply moves the 'work' of the individual jobs into the main thread when you call the 'processSwarmJobs' pump method.&lt;br /&gt;&lt;br /&gt;I am releasing this JobSwarm code for a reason.  First, I hope other people might adopt it and improve the code and I would, thereby, benefit from it.  I was also frustrated in my efforts to find a very tiny and simple micro-threading solution by searching on the net.&lt;br /&gt;&lt;br /&gt;This system could use some improvements.  For example, in addition to needing a true lock-free FIFO, it also might be nice if it supported job priorities.&lt;br /&gt;&lt;br /&gt;It also might be interesting to support inter-job communication, if that sort of thing made sense and/or was useful.&lt;br /&gt;&lt;br /&gt;I am making this code available in two forms.&lt;br /&gt;&lt;br /&gt;First, as a small console application with just a tiny amount of source code.&lt;br /&gt;&lt;br /&gt;You can download it from &lt;a href="http://www.amillionpixels.us/JobSwarm.zip"&gt;JobSwarm.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The source included with 'JobSwarm.zip' is as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;fractal.cpp and fractal.h &lt;/span&gt;: A very simple fractal routine which can solve the fractal in a linear fashion or by breaking it up into 65,536 distinct 'jobs'.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;JobSwarm.cpp and JobSwarm.h&lt;/span&gt; : The main JobSwarm system.  Has no OS dependent code in it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;LockFreeQ.cpp and LockFreeQ.h&lt;/span&gt; : Provides a lock-free circular queue for a single provider / single consumer system.  Also provides an API for a lock free FIFO, however the implementation currently does use locks.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;main.cpp&lt;/span&gt; : The console demo/test app.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;pool.h&lt;/span&gt; : A double linked list template class used by the JobSwarm to manage jobs.  Minimizes memory allocations.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;sgif.cpp and sgif.h&lt;/span&gt; : A snippet of code to save a block of memory as a GIF image.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;ThreadConfig.cpp and ThreadConfig.h&lt;/span&gt; : A wrapper layer to hide OS dependencies for threading related calls.  Intended to be multi-platform but the current implementation is only for Windows.&lt;br /&gt;&lt;br /&gt;The second application is a larger framework called 'ThreadFrac', which provides an interactive graphics application which allows you to visually see the performance differences when toggling the job swarm on and off on multi-core machines.&lt;br /&gt;&lt;br /&gt;You can download and install it from &lt;a href="http://www.amillionpixels.us/ThreadFrac_1.0.exe"&gt;ThreadFrac.exe&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I look forward to bug-fixes, improvements, and feedback from the development community.&lt;br /&gt;&lt;br /&gt;Thanks,&lt;br /&gt;&lt;br /&gt;John&lt;br /&gt;&lt;br /&gt;--------------------- Revision update January 3, 2009 --------------&lt;br /&gt;&lt;br /&gt;I made the following important revisions to the &lt;a href="http://www.amillionpixels.us/JobSwarm.zip"&gt;JobSwarm.zip&lt;/a&gt; download.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I removed the source files 'fractal.cpp' and 'fractal.h'&lt;/li&gt;&lt;li&gt;I revised the 'main.cpp' to act as a much simpler example program on how to use the JobSwarm system.  Simply look through and/or step through the code that is there.&lt;/li&gt;&lt;li&gt;I created  two separate examples of how to use the JobSwarm system.&lt;/li&gt;&lt;li&gt;First : One class with a callback interface is created for each separate job.  This may be the most common use case but requires more setup and memory allocation in some use cases.&lt;/li&gt;&lt;li&gt;Second: A single class receives callbacks for all of the 'jobs' and it uses the user data and user id field to figure out just what needs to be calculated in that context.&lt;/li&gt;&lt;li&gt;I added support for a userData and userId field for jobs.  This extra meta data is available as an optional additional information to pass into the job service callbacks.&lt;/li&gt;&lt;li&gt;I fixed a crash bug that would happen occasionally when trying to deconstruct the JobSwa&lt;a id="publishButton" class="cssButton" href="javascript:void(0)" onclick="if (this.className.indexOf(&amp;quot;ubtn-disabled&amp;quot;) == -1) {var e = document['stuffform'].publish;(e.length) ? e[0].click() : e.click(); if (window.event) window.event.cancelBubble = true; return false;}"&gt;&lt;/a&gt;rmContext&lt;/li&gt;&lt;li&gt;This version was built with VC2008.  If you have an earlier version of VC you won't be able to load the solution and project files.  Simply create a new console app and add the source files, that is all you need to build the example program.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Thanks to everyone who previously downloaded the sample and gave me feedback.  It was all very useful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-8918545798368647470?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/JobSwarm.zip' title='JobSwarm : A microthreading framework with lockless FIFO'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/8918545798368647470/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=8918545798368647470' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8918545798368647470'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8918545798368647470'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2009/01/jobswarm-microthreading-framework-with.html' title='JobSwarm : A microthreading framework with lockless FIFO'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/SV5Xgj4BGhI/AAAAAAAAGE4/24nko97gXdM/s72-c/swarm.jpg' height='72' width='72'/><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-895074834376242376</id><published>2008-11-28T10:53:00.001-08:00</published><updated>2008-12-01T11:08:22.743-08:00</updated><title type='text'>CodeSuppository.exe : A Graphics/Demo framework for the Code Suppository Code Snippets</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PtTKwwh_xBc/STA-iDi958I/AAAAAAAAEJE/yf_B57dYtI4/s1600-h/1s2.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 399px;" src="http://4.bp.blogspot.com/_PtTKwwh_xBc/STA-iDi958I/AAAAAAAAEJE/yf_B57dYtI4/s400/1s2.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5273783918439294914" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As promised, here is a new demo framework called &lt;a href="http://www.amillionpixels.us/CodeSuppository_1.0.exe"&gt;'CodeSuppository.exe'&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This framework provides a graphical demonstration of various code snippets on this site.  The project installs to \Program Files\CodeSuppository&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The source file \Program Files\CodeSuppository\app\CodeSuppository\CodeSuppository.cpp  is specifically designed to visually demonstrate the usage of various code snippets.  This initial release only demonstrates explicitely two snippets.  The best fit OBB routine and the best fit plane.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Over time I will revise this to include more and more demos.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;---------Note: I just re-uploaded the code, and I also improved the OBB fitting algorithm.  It now uses the best fit plane technique to derive a rotation matrix to fit the point cloud and then only rotates the points on a single axis of rotation to converge to the best fit solution.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-895074834376242376?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/895074834376242376/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=895074834376242376' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/895074834376242376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/895074834376242376'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2008/11/codesuppositoryexe-graphicsdemo.html' title='CodeSuppository.exe : A Graphics/Demo framework for the Code Suppository Code Snippets'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PtTKwwh_xBc/STA-iDi958I/AAAAAAAAEJE/yf_B57dYtI4/s72-c/1s2.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-977641732632511436</id><published>2008-11-28T07:54:00.001-08:00</published><updated>2008-12-01T11:08:36.633-08:00</updated><title type='text'>How to use the OBB fitting code</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_PtTKwwh_xBc/STAUcLZP9mI/AAAAAAAAEI8/FcF0Sv36TgA/s1600-h/IMG_0258.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://2.bp.blogspot.com/_PtTKwwh_xBc/STAUcLZP9mI/AAAAAAAAEI8/FcF0Sv36TgA/s400/IMG_0258.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5273737637978437218" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have received a number of emails from people who are confused about how to use my various code snippets. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have decided that, in the future, I am going to present my code snippets in the form of a single large graphics application.  At first you might think this defeats the purpose of the 'snippets' concept, but really I don't think it does.  The code will still be in snippet form, but will come packaged in a framework that demonstrates the usage pattern.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example, some poeple have complained that my OBB fitting code doesn't work.  I know this is not true, because I use the OBB fitting routine in production code all of the time.  It's most likely they are just using the routine incorrectly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But placing the code snippet in a graphics framework, I can actually draw a point cloud and the resulting OBB produced so that people can get a clear visual demonstration that it is, in fact, working.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sometime in the next couple of weeks I will be uploading my code snippets in this single package format.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A lot of the math based code snippets are now folded into a single piece of source called 'FloatMath'.   The design of FloatMath is that, even though it is a single large source file, individual code snippets and routines can be extracted from it.  Or, you can just use the whole file if you prefer.  It is turning out to be an excellent reference for a wide variety of math and geometric computation routines.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The FloatMath library has been refactored so that it supports both 'float' and 'double' types of all of the routines.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It is comprised of three source files.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.h"&gt;FloatMath.h&lt;/a&gt;         : which contains the prototypes for all of the routines.&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.inl"&gt;FloatMath.inl &lt;/a&gt;      : which contains the conditionally compiled implementation&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.cpp"&gt;FloatMath.cpp&lt;/a&gt;    : which includes FloatMath.inl twice to produce both the 'float' and the 'double' implemnetations of each method.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have also uploaded a small zip file that shows how to call the OBB fitting routines.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.amillionpixels.us/obb.zip"&gt;obb.zip&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;---------Note: I just re-uploaded the code, and I also improved the OBB fitting algorithm.  It now uses the best fit plane technique to derive a rotation matrix to fit the point cloud and then only rotates the points on a single axis of rotation to converge to the best fit solution.  &lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-977641732632511436?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/977641732632511436/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=977641732632511436' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/977641732632511436'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/977641732632511436'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2008/11/how-to-use-obb-fitting-code.html' title='How to use the OBB fitting code'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_PtTKwwh_xBc/STAUcLZP9mI/AAAAAAAAEI8/FcF0Sv36TgA/s72-c/IMG_0258.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-8953369777727008999</id><published>2008-06-24T09:50:00.001-07:00</published><updated>2008-06-24T10:03:10.707-07:00</updated><title type='text'>Instant Messaging API code snippet</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_PtTKwwh_xBc/SGEmFlJBDuI/AAAAAAAAEDE/pJHGGbmQaEs/s1600-h/october_07_33.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp2.blogger.com/_PtTKwwh_xBc/SGEmFlJBDuI/AAAAAAAAEDE/pJHGGbmQaEs/s400/october_07_33.jpg" alt="" id="BLOGGER_PHOTO_ID_5215491720782876386" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;On the post I made yesterday I presented a code snippet for sending an email in your application.  Today I am including a code snippet that lets you send and receive messages using an Instant Messaging application.&lt;br /&gt;&lt;br /&gt;All this snippet really does is provide a simple and convenient wrapper for the &lt;a href="http://dev.aol.com/aim"&gt;AIM Developer SDK.&lt;/a&gt;  I have read the license that is included and it seems pretty open and allows for the redistribution of source and binaries.&lt;br /&gt;&lt;br /&gt;The wrapper is provided with a single header file and single CPP for implementation as all true snippets should be.  However, since it is dependent on the AIM SDK it does require the AIM SDK header files, link libraries, and run-time DLL components (all included in this download).&lt;br /&gt;&lt;br /&gt;This download includes a fully built executable console chat-client as well as the source code and project files to build it.  Obviously this is a Windows only feature (as was the SendMail submission yesterday).&lt;br /&gt;&lt;br /&gt;The wrapper uses a version of the &lt;a href="http://en.wikipedia.org/wiki/Opaque_pointer"&gt;PIMPL pattern&lt;/a&gt; that I have become pretty happy with.  It exposes just two standard C style methods, one to create an 'InstantMessage' interface and one to release it.  The pointer you get back is a pure-virtual interface that only exposes the public methods and nothing more.&lt;br /&gt;&lt;br /&gt;When constructing the InstantMessage system you will need to pass a pointer to an 'InstantMessageInterface' so that you can receive incoming messages.  You will also need to pump the InstantMessage class to give it a chance to process incoming messages and state change events.&lt;br /&gt;&lt;br /&gt;The public interface is completely generic and could, theoretically, be mapped to other instant messaging systems.  The main use-case for this implementation is for server status monitoring.  I am using it to have live servers fire of chat messages to me based on state changes and other important events.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/InstantMessage.zip"&gt;Here is a link to the the zip file &lt;/a&gt;containing the source code, binaries, and everything you need to embed instant messaging capabilities (using AIM) in your application.&lt;br /&gt;&lt;br /&gt;Here is the header file for the Instant Messaging wrapper layer&lt;br /&gt;------------------------------------------------&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;#ifndef INSTANT_MESSAGE_H&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;#define INSTANT_MESSAGE_H&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;// This is a wrapper API to handle instant messaging on top of AOL instant messenger or AIM&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;// Requires the AIM instant message SDK to build.&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;//&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;// Please be aware of all of the licensing issues associated with using the AIM SDK&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;//&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;// This wrapper was written by John W. Ratcliff.  Please send bug-fixes feedback to jratcliff@infiniplex.net&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;enum InstantMessageState&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;{&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_NONE,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_OFFLINE,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_DISCONNECTED,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_QUERYING_DCS,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_CONNECTING,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_CHALLENGING,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_VALIDATING,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_SECURE_ID,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_SECURET_ID_NEXT_KEY,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_TRANSFERRING,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_NEGOTIATING,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_STARTING,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_ONLINE,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_WILL_SHUTDOWN,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_SHUTDOWN,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  IMS_PAUSED,&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;};&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;class InstantMessageInterface&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;{&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;public:&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  virtual void notifyInstantMessageState(InstantMessageState state) = 0;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  virtual void receiveInstantMessage(const wchar_t *from,const wchar_t *message) = 0;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;};&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;class InstantMessage&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;{&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;public:&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  virtual bool connect(const char *userName,const char *password) = 0;  // connect using this user id and password.&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  virtual bool disconnect(void) = 0; // dissconnected&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  virtual bool pump(void) = 0; // pump the instant message system on this thread, handles event processing.&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  virtual const char * getInstantMessageStateStr(InstantMessageState state) = 0; // conver the instant message enum into a string.&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  virtual bool sendInstantMessage(const wchar_t *userId,const wchar_t *msg) = 0; // send an instant message to a buddy (unicode string)&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;  virtual bool sendInstantMessage(const char *userId,const char *fmt,...) = 0;  // send an instant message to a buddy using the printf style syntax&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;};&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;InstantMessage * createInstantMessage(InstantMessageInterface *imi);&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;void             releaseInstantMessage(InstantMessage *im);&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:100%;"&gt;#endif&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-8953369777727008999?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/InstantMessage.zip' title='Instant Messaging API code snippet'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/8953369777727008999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=8953369777727008999' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8953369777727008999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8953369777727008999'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2008/06/instant-messaging-api-code-snippet.html' title='Instant Messaging API code snippet'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_PtTKwwh_xBc/SGEmFlJBDuI/AAAAAAAAEDE/pJHGGbmQaEs/s72-c/october_07_33.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-2032845812778069454</id><published>2008-06-23T08:21:00.000-07:00</published><updated>2008-06-23T14:47:49.000-07:00</updated><title type='text'>SendMail : Send mail using embedded Blat</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_PtTKwwh_xBc/SF_AE_LdPyI/AAAAAAAAECw/BHhxtJNTttw/s1600-h/stare_fotografie_17.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_PtTKwwh_xBc/SF_AE_LdPyI/AAAAAAAAECw/BHhxtJNTttw/s400/stare_fotografie_17.jpg" alt="" id="BLOGGER_PHOTO_ID_5215098085429821218" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I am uploading today a code snippet of somewhat questionable value.  This is a true snippet, in that it is composed of a single .CPP and .H file.  In a simple one line API call you can send an email from your code.  You can download the source, project, and executable using this link &lt;a href="http://www.amillionpixels.us/SendMail.zip"&gt;SendMail.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;My specific use case for this is that I need to be able to get notifications from a remote server when it is in a bad state.  What I really want to do is just send an instant message.  However, after searching the Internet, I realized that it was going to be extremely difficult to find a true code snippet which could do such a thing.  Theoretically Jabber would allow me to do this, but all of the source code libraries for Jabber are simply massive and include insane amounts of graphics/UI code.  Even the one or two console versions of Jabber are still overwhelming.&lt;br /&gt;&lt;br /&gt;If anyone knows of an implementation of an instant messaging API that allows me to simple use the form of send message 'from' this person 'to' this person with 'this subject' and 'this text', that would be awesome.&lt;br /&gt;&lt;br /&gt;In the meantime I have resorted to sending emails.  &lt;a href="http://www.blat.net/"&gt;Blat&lt;/a&gt; is a simply awesome full public domain console email program.  You can use it either as a console executable or as a DLL.&lt;br /&gt;&lt;br /&gt;What I have done is created a single CPP file that not only provides a simple wrapper routine to send an email but also contains, embedded within it, the Blat DLL.    Simply add this one CPP and header file to your project and you can transmit an email message in your program.&lt;br /&gt;&lt;br /&gt;The DLL is loaded directly from memory, not from a file on disk, using the routing MemoryModule written by Joachim Bauch.  &lt;a href="http://www.joachim-bauch.de/tutorials/load_dll_memory.html"&gt;See his full article here.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Like I said, this may be of questionable value but if you are looking for a completely turnkey way of just sending an email from inside your program this will do it.  You could always just add the blat source code to your project, which is an entirely viable option, but there is  a lot of source in Blat and this form might be easier to use.&lt;br /&gt;&lt;br /&gt;The file 'SendMail.h' provides two methods.  The first is as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;bool sendMail(const char *mail_server,   // mail server to use for sending the email message.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;              const char *from,          // email address of the sender&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;              const char *to,            // email address to send to.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;              const char *subject,       // the subject line of the email.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;              const char *body,          // the body text of the email.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;              const char *attachment);   // an optional attachment file.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The second option is to just invoke the Blat dll function directly.  In which case you will need to familiarize yourself with the full Blat command line interface which has a lot of options.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;bool sendBlat(int argc,const char *argv[]); // refer to the Blat documentation for the full set of command line arguments.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Another cool way to use this program is to send SMS text messages to your mobile phone.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Sending SMS through email is very, very easy.  If you can be reminded through email, you can now be reminded through SMS.&lt;/h3&gt;If you know the correct email address, you can also send these messages to your cellular phone. Here are the email addresses for the 6 most popular cellular phone carriers:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;T-Mobile:&lt;/span&gt;&lt;span style="font-style: italic;"&gt;phonenumber&lt;/span&gt;@&lt;span style="font-weight: bold;"&gt;tmomail.net &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Virgin Mobile:&lt;/span&gt;&lt;span style="font-style: italic;"&gt;phonenumber&lt;/span&gt;@&lt;span style="font-weight: bold;"&gt;vmobl.com &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Cingular:&lt;/span&gt;&lt;span style="font-style: italic;"&gt;phonenumber&lt;/span&gt;@&lt;span style="font-weight: bold;"&gt;cingularme.com &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sprint:&lt;/span&gt;&lt;span style="font-style: italic;"&gt;phonenumber&lt;/span&gt;@&lt;span style="font-weight: bold;"&gt;messaging.sprintpcs.com&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Verizon: &lt;/span&gt;&lt;span style="font-style: italic;"&gt;phonenumber&lt;/span&gt;@&lt;span style="font-weight: bold;"&gt;vtext.com&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Nextel: &lt;/span&gt;&lt;span style="font-style: italic;"&gt;phonenumber&lt;/span&gt;@&lt;span style="font-weight: bold;"&gt;messaging.nextel.com &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;where &lt;span style="font-style: italic;"&gt;phonenumber&lt;/span&gt; = &lt;span style="font-weight: bold;"&gt;your 10 digit phone number&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-2032845812778069454?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.blat.net/' title='SendMail : Send mail using embedded Blat'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/2032845812778069454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=2032845812778069454' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2032845812778069454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2032845812778069454'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2008/06/sendmail-send-mail-using-embedded-blat.html' title='SendMail : Send mail using embedded Blat'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_PtTKwwh_xBc/SF_AE_LdPyI/AAAAAAAAECw/BHhxtJNTttw/s72-c/stare_fotografie_17.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-1138580146020183568</id><published>2008-06-23T08:09:00.000-07:00</published><updated>2008-06-23T08:19:52.397-07:00</updated><title type='text'>D3DXQuaternionRotationYawPitchRoll</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_PtTKwwh_xBc/SF-9LMsek-I/AAAAAAAAECo/gFy6xZBNagM/s1600-h/Don%27t-overload-your-trailer.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_PtTKwwh_xBc/SF-9LMsek-I/AAAAAAAAECo/gFy6xZBNagM/s400/Don%27t-overload-your-trailer.jpg" alt="" id="BLOGGER_PHOTO_ID_5215094893602313186" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I am going to refrain from a full blown rant here.  That said, I cannot reiterate enough how f**king annoying it is that Microsoft goes as far out their way as possible to make it difficult for people to develop multi-platform code using their tools.  When Microsoft released Visual Studio 2005 and had the unmitigated gall to issue a warning message for 'printf' I about blew a gasket.  Now my code is littered with '#pragma warning(disable:4996)' to prevent VS2005 from throwing warnings everywhere for 100% perfectly ANSII C compliant code!!!!!!!!!!&lt;br /&gt;&lt;br /&gt;Another problem we encounter is when people start using the D3DX library; which is not provided with source code.  Recently I have needed to refactor some source that made use of the D3DX library for various math routines.&lt;br /&gt;&lt;br /&gt;One problematic routine in particular is 'D3DXQuaternionRotationYawPitchRoll'  which, for whatever reason, and at this point I don't even care, Microsoft implemented in a non-standard way.  Since you don't get source code to D3DX there is no easy way to figure out what they did (turns out they flipped a couple of signs during the computation).  Stepping into the disassembly just uncovers a whole bunch of cryptic SSE instructions that are not that illuminating.&lt;br /&gt;&lt;br /&gt;Finally a very helpful Microsoft engineer posted the solution on the DirectX mailing list.  I am going to repost the solution here so that anyone else who ever needs to know the formula has it.&lt;br /&gt;&lt;br /&gt;Here is the correct formulation for D3DXQuaternionRotationYawPitchRoll.&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;void QuaternionRotationYawPitchRoll(float yaw,float pitch,float roll,float quat[4])&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  float sinY, cosY, sinP, cosP, sinR, cosR;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  sinY = sinf(0.5f * yaw);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  cosY = cosf(0.5f * yaw);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  sinP = sinf(0.5f * pitch);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  cosP = cosf(0.5f * pitch);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  sinR = sinf(0.5f * roll);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  cosR = cosf(0.5f * roll);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  quat[0] = cosY * sinP * cosR + sinY * cosP * sinR;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  quat[1] = sinY * cosP * cosR - cosY * sinP * sinR;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  quat[2] = cosY * cosP * sinR - sinY * sinP * cosR;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  quat[3] = cosY * cosP * cosR + sinY * sinP * sinR;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-1138580146020183568?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://msdn.microsoft.com/en-us/library/bb205417(VS.85).aspx' title='D3DXQuaternionRotationYawPitchRoll'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/1138580146020183568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=1138580146020183568' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1138580146020183568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1138580146020183568'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2008/06/d3dxquaternionrotationyawpitchroll.html' title='D3DXQuaternionRotationYawPitchRoll'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_PtTKwwh_xBc/SF-9LMsek-I/AAAAAAAAECo/gFy6xZBNagM/s72-c/Don%27t-overload-your-trailer.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-7291958351674224621</id><published>2008-05-21T09:59:00.000-07:00</published><updated>2008-05-21T10:08:56.883-07:00</updated><title type='text'>Code Snippet to Render a 3d oriented Arrowhead for debug visualization</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_PtTKwwh_xBc/SDRVPSqnBrI/AAAAAAAADsI/J_CDQXyscdI/s1600-h/arrow.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp2.blogger.com/_PtTKwwh_xBc/SDRVPSqnBrI/AAAAAAAADsI/J_CDQXyscdI/s400/arrow.jpg" alt="" id="BLOGGER_PHOTO_ID_5202877190716720818" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Today in true code-snippet form I am releasing a handy little debug function that will generate an oriented 3d arrowhead as 24 triangles.  This routine will properly orient the arrow head so it faces the correct direction of the line segment it is associated with.&lt;br /&gt;&lt;br /&gt;The API is implemented as a single function call that accepts a starting and ending location, and a size for the arrow head.  It returns the triangle count and a const float pointer array of triangles as nine floats, x1,y1,z1, x2,y2,z2, and x3,y3,z3.  Simply pass these triangles off to your favorite debug rendering library and you will get nicely formed and oriented debug arrow heads that make visualizing ray segments much easier.&lt;br /&gt;&lt;br /&gt;The image above shows the debug visualization of the arrow head in my split mesh tool.  Note that the interior of the arrow head is slightly hollowed out, which improves the debug visualization in my opinion.&lt;br /&gt;&lt;br /&gt;The source files can be downloaded here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/ArrowHead.h"&gt;ArrowHead.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/ArrowHead.cpp"&gt;ArrowHead.cpp&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-7291958351674224621?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/arrowhead.cpp' title='Code Snippet to Render a 3d oriented Arrowhead for debug visualization'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/7291958351674224621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=7291958351674224621' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/7291958351674224621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/7291958351674224621'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2008/05/code-snippet-to-render-3d-oriented.html' title='Code Snippet to Render a 3d oriented Arrowhead for debug visualization'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_PtTKwwh_xBc/SDRVPSqnBrI/AAAAAAAADsI/J_CDQXyscdI/s72-c/arrow.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-4212452193189481273</id><published>2008-05-06T18:51:00.000-07:00</published><updated>2008-05-14T18:40:21.944-07:00</updated><title type='text'>SplitMesh in development release</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_PtTKwwh_xBc/SCEM3CB_tTI/AAAAAAAADr4/bxj_uB9B_qo/s1600-h/splitmesh.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp2.blogger.com/_PtTKwwh_xBc/SCEM3CB_tTI/AAAAAAAADr4/bxj_uB9B_qo/s400/splitmesh.jpg" alt="" id="BLOGGER_PHOTO_ID_5197449584539841842" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I have just uploaded an extremely early developer release of my SplitMesh tool.  You can download and install it using &lt;a href="www.amillionpixels.us/SplitMesh_1.0.exe"&gt;this link.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Let me give you a really quick walk-thru.  The download is only about 8mb and comes with a handy Windows installer.  Once it is installed, go to the start menu and run SplitMesh.exe&lt;br /&gt;&lt;br /&gt;Once the program has started up you will see a series of yellow concentric circles on the screen that represents the current split plane.  You can move the split plane up and down using the Plane-D offset slider.  You can also use the combo box to change the main axis of the split plane.  Even though this demo just lets you set up the X, Y, and Z axis, the code doesn't care what the plane equation is.  On a future drop I will have some sliders that let you freely orient the split plane on all axes.&lt;br /&gt;&lt;br /&gt;The next thing you need to do is import a Wavefront OBj file to experiment with.  I have provided several with the install.  Simply browse to "\Program Files\SplitMesh\media\PhysXViewer"&lt;br /&gt;&lt;br /&gt;You might start by loading the file 'sphere.obj'.  The character model 'beshon.obj' (pictured above) is also interesting to play with.&lt;br /&gt;&lt;br /&gt;There are a number of checkboxes that allow you to selectively turn on and off the various visualizations of the exploded split mesh.&lt;br /&gt;&lt;br /&gt;This release has the source code in it but, as I said, it is still in an early stage of development and does not represent what the final source will look like.&lt;br /&gt;&lt;br /&gt;The finished version will be provided as a single CPP file which will allow you to split any mesh into two perfectly capped/closed meshes in a single API call.&lt;br /&gt;&lt;br /&gt;This version has a number of bugs in it which I am still working on.  I just released this build because it is kind of fun to play with the interactive visualization of the split mesh.&lt;br /&gt;&lt;br /&gt;Right now my main blocking points are:&lt;br /&gt;&lt;br /&gt;(1) Sometimes when I walk the edges to come up with perfectly matched polygonal rings, it fails.  You will see this indicated at times when the split mesh is not properly capped.&lt;br /&gt;&lt;br /&gt;(2) This version does not yet deal with holes.  An example of a whole would be if you cut say a drinking glass in half.  This is still a major todo item.&lt;br /&gt;&lt;br /&gt;(3) Sometimes it classifies convex polygons as concave; I'm not quite sure why yet.&lt;br /&gt;&lt;br /&gt;In the visualization if you see a capped surface in green, this indicates that it the polygon was properly identified as a convex surface.  The triangulation will fan out from the center of the polygon.&lt;br /&gt;&lt;br /&gt;If you see a split surface colored in a more reddish tint, this indicates that the polygon was detected as being concave and was sent through a more robust triangulation routine that can handle this case.   I note that there are some cases where I still flag convex polygons as concave; I haven't quite figured this one out yet. &lt;br /&gt;&lt;br /&gt;Here are the features I intend to add to the tool and the order of their release.&lt;br /&gt;&lt;br /&gt;Release version #1:&lt;br /&gt;&lt;br /&gt;(1) Should handle all cases for split meshes *without* holes.&lt;br /&gt;&lt;br /&gt;(2) Will come with a single CPP file 'SplitMesh.cpp' and a header that prototypes a method that will allow you to split a mesh by a plane in a single function call.&lt;br /&gt;&lt;br /&gt;(3) Will come with a simple console application 'SplitMeshObj', which will read a Wavefront OBJ file in, split it by a plane, and write two Wavefront OBJ files out.  The only source required will be SplitMeshObj.cpp, SplitMesh.cpp and SplitMesh.h&lt;br /&gt;&lt;br /&gt;(4) It will include the full interactive graphics demo as above to experiment with your own meshes.&lt;br /&gt;&lt;br /&gt;(5) It will include a revised copy of the ConvexDecomposition library which will use the new SplitMesh routine to produce much more efficient and effective convex decomposition solutions.&lt;br /&gt;&lt;br /&gt;Release #2&lt;br /&gt;&lt;br /&gt;(1) Will handle splits with holes.&lt;br /&gt;&lt;br /&gt;(2) Will allow the user to add perlin noise to the split surface to create jagged or rough edged splits.&lt;br /&gt;&lt;br /&gt;(3) The convex decomposition library will be revised to return not only the convex hull pieces, but also the corresponding fracture graphics.&lt;br /&gt;&lt;br /&gt;Release #3&lt;br /&gt;&lt;br /&gt;(1) Will add support for textures, U/V co-ordinates, and user provided per-vertex interpolants.&lt;br /&gt;&lt;br /&gt;(2) Will be integrated into the Nvidia PhysX SDK to demonstrate real-time fracture of graphics models, using the convex decomposition library and the create dynamics toolkit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-4212452193189481273?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/SplitMesh_1.0.exe' title='SplitMesh in development release'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/4212452193189481273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=4212452193189481273' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/4212452193189481273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/4212452193189481273'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2008/05/splitmesh-in-development-release.html' title='SplitMesh in development release'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_PtTKwwh_xBc/SCEM3CB_tTI/AAAAAAAADr4/bxj_uB9B_qo/s72-c/splitmesh.jpg' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-8446390371694057030</id><published>2008-05-05T09:05:00.000-07:00</published><updated>2008-05-05T09:24:34.588-07:00</updated><title type='text'>SplitMesh</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_PtTKwwh_xBc/SB8wsyB_tSI/AAAAAAAADrw/_n0QE0K7sjU/s1600-h/83461.JPG"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_PtTKwwh_xBc/SB8wsyB_tSI/AAAAAAAADrw/_n0QE0K7sjU/s400/83461.JPG" alt="" id="BLOGGER_PHOTO_ID_5196926040911361314" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Just a heads up about something I am working on.  I am pleased that my convex decomposition library has been useful for some developers.  However, one thing has really bugged me about that tool since it was never really finished.  In the current version, when the decomposition process occurs, I do not create closed meshes.  Because of this, as you recurse deeper trying to find the optimal solution the algorithm ends up converging on the interior sections of the splits, thereby creating a hollow objects.&lt;br /&gt;&lt;br /&gt;Clearly this is not the desired result in the general case.  If each split were treated as a closed mesh, then you could recurse more deeply and converge more accurately towards an optimal solution.  I never got around to finishing this step but, this week, I am going to take another crack at the problem.&lt;br /&gt;&lt;br /&gt;The main reason I maintain a 'code suppository' is so that I can insert code capsules in the anus of the Internet (otherwise known as Blogger) as an attempt to repay the development community for the massive amounts of source code I have begged, borrowed or stolen in the past.&lt;br /&gt;&lt;br /&gt;In that vein, I always try to find something suitable in the public domain before I resort to the painful process of coding it myself.  However, in all of my searching I have yet to find a simple routine (i.e. a 'snippet') which you can submit a triangle mesh and a splitting plane and get two closed meshes as a result. &lt;br /&gt;&lt;br /&gt;I did find an excellent &lt;a href="http://www.diku.dk/publikationer/tekniske.rapporter/rapporter/06-09.pdf"&gt;published paper&lt;/a&gt; on the topic and I intend to code my implementation fairly closely to it.  I sent an email to the paper's author, asking him if he wouldn't mind just 'giving' me the source code but this blatant attempt at begging resulted in a deafening inbox silence.&lt;br /&gt;&lt;br /&gt;At this point, I'm looking forward to just writing it myself as I am kind of excited about implementing it as a true source code 'snippet'.&lt;br /&gt;&lt;br /&gt;In addition to improving my convex decomposition library the split mesh routine will also prove invaluable for implementing real-time fracture.  While the convex decomposition process will produce excellent physics models for fracturing objects, you are still left with the technical challenge of producing the fractured graphics model to match; replete with jagged edges where the object has been smashed in two.&lt;br /&gt;&lt;br /&gt;My idea is that first I will perform a clean plane split producing two closed meshes nicely sliced.  I will then take the polygonal surfaces at the slice boundary, project them into 2d, tessellate the surface, and apply a perlin noise function on it.  Finally I will apply U/V coordinates and map a nice looking texture that represents the internal surface of the broken object. &lt;br /&gt;&lt;br /&gt;This should produce nice rough looking broken surfaces and by tweaking the material properties, UV mapping, and perlin noise function can be made to look like broken rock, or jagged edges, whatever your artist might design.&lt;br /&gt;&lt;br /&gt;I hope the implementation will be fast enough that this process can occur in real-time and allow for interactive fracture of dynamic objects in a game.&lt;br /&gt;&lt;br /&gt;Again, I plan to do this little project entirely open source and public domain, so I have only two questions.&lt;br /&gt;&lt;br /&gt;(1) If you have already written something that does this and are willing to share, save me some time and let me know!?&lt;br /&gt;&lt;br /&gt;(2) If you find the code useful, won't you do something nice for me?  Karma only works if you pay it forward from time to time.&lt;br /&gt;&lt;br /&gt;I will be at the &lt;a href="http://www.ionconference.com/"&gt;ION conference&lt;/a&gt; in Seattle next week to give a presentation.  I hope to visit with some of you then.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-8446390371694057030?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.diku.dk/publikationer/tekniske.rapporter/rapporter/06-09.pdf' title='SplitMesh'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/8446390371694057030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=8446390371694057030' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8446390371694057030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8446390371694057030'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2008/05/splitmesh.html' title='SplitMesh'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_PtTKwwh_xBc/SB8wsyB_tSI/AAAAAAAADrw/_n0QE0K7sjU/s72-c/83461.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-7209995653585063067</id><published>2008-03-25T16:29:00.000-07:00</published><updated>2009-12-02T12:21:05.854-08:00</updated><title type='text'>Compression / Decompression : Comparing Apples to Apples</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_PtTKwwh_xBc/R-mLZ8G7_SI/AAAAAAAADiU/grsmikJcb14/s1600-h/1807117807_6ade84c3af.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_PtTKwwh_xBc/R-mLZ8G7_SI/AAAAAAAADiU/grsmikJcb14/s400/1807117807_6ade84c3af.jpg" alt="" id="BLOGGER_PHOTO_ID_5181826124014681378" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(Note: This library has been updated.  Go to the &lt;a href="http://codesuppository.blogspot.com/2009/12/compression-test.html"&gt;following post&lt;/a&gt; to find the latest information. It is now hosted officially on &lt;a href="http://code.google.com/p/compressiontest/"&gt;Google Code&lt;/a&gt;.)&lt;br /&gt;&lt;div class="Section1"&gt;&lt;br /&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;With pretty much every  developer there comes a time when you need to use a compression library; not  because you want to ‘zip’ up a massive archive but more because you want to  compress some game data on the fly before you transmit it over the network, or  to shrink the size of a local cache or something.  And, like pretty much every  developer, you end up wandering through a maze of open source libraries on the  internet, each of which has entirely different API, source code layout, and  license agreement.  Just figuring out to call ‘compressData’ (if you even can)  is often hours of wading through documentation and dealing with  build/configuration issues.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;For your convenience I am  releasing a small code snippet that I wrote when I was trying to evaluate a  replacement compression library than the one we are currently using.  The simple  fact of the matter is that I don’t believe any other programmer should have to  waste the same amount of stupid time I did wrestling these libraries into a  convenient form.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;a title="blocked::http://www.amillionpixels.us/test_compression_1.0.exe" href="http://www.amillionpixels.us/test_compression_1.0.exe"&gt;http://www.amillionpixels.us/test_compression_1.0.exe&lt;/a&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;Here is the complete API to  my wrapper interface:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;div style="border-style: none none solid; padding: 0in 0in 1pt;"&gt; &lt;p class="MsoNormal" style="border: medium none ; padding: 0in;"&gt;&lt;span style=";font-family:Arial;font-size:85%;"  &gt;&lt;span style=";font-family:Arial;font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;// Block  compression/decompression library wrapper by John W. Ratcliff &lt;a title="blocked::http://www.codesuppository.blogspot.com/" href="http://www.codesuppository.blogspot.com/"&gt;http://www.codesuppository.blogspot.com/&lt;/a&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;color:blue;"   &gt;&lt;span style=";font-family:'Courier New';font-size:10px;color:blue;"   &gt;enum&lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt; &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;CompressionType&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;  &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;CT_INVALID&lt;/span&gt;&lt;/span&gt;,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;  &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;CT_CRYPTO_GZIP&lt;/span&gt;&lt;/span&gt;,       &lt;span style="color:green;"&gt;&lt;span style="color:green;"&gt;// The CryptoPP library implementation of  GZIP   http://www.cryptopp.com&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;  &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;CT_MINILZO&lt;/span&gt;&lt;/span&gt;,           &lt;span style="color:green;"&gt;&lt;span style="color:green;"&gt;// The MiniLZO library   http://www.oberhumer.com/opensource/lzo/&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;  &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;CT_ZLIB&lt;/span&gt;&lt;/span&gt;,              &lt;span style="color:green;"&gt;&lt;span style="color:green;"&gt;// The ZLIB library    http://www.zlib.net/&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;  &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;CT_BZIP&lt;/span&gt;&lt;/span&gt;,              &lt;span style="color:green;"&gt;&lt;span style="color:green;"&gt;// The BZIP library   http://www.bzip.org/&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;};&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;color:blue;"   &gt;&lt;span style=";font-family:'Courier New';font-size:10px;color:blue;"   &gt;void&lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt; *           &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;compressData&lt;/span&gt;&lt;/span&gt;(&lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;const&lt;/span&gt;&lt;/span&gt; &lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt;&lt;/span&gt; *&lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;source&lt;/span&gt;&lt;/span&gt;,&lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;len&lt;/span&gt;&lt;/span&gt;,&lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&lt;/span&gt; &amp;amp;&lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;outlen&lt;/span&gt;&lt;/span&gt;,&lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;CompressionType&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;type&lt;/span&gt;&lt;/span&gt;=&lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;CT_ZLIB&lt;/span&gt;&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;color:blue;"   &gt;&lt;span style=";font-family:'Courier New';font-size:10px;color:blue;"   &gt;void&lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt; *           &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;decompressData&lt;/span&gt;&lt;/span&gt;(&lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;const&lt;/span&gt;&lt;/span&gt; &lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt;&lt;/span&gt; *&lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;source&lt;/span&gt;&lt;/span&gt;,&lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;clen&lt;/span&gt;&lt;/span&gt;,&lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&lt;/span&gt; &amp;amp;&lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;outlen&lt;/span&gt;&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;color:blue;"   &gt;&lt;span style=";font-family:'Courier New';font-size:10px;color:blue;"   &gt;void&lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;             &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;deleteData&lt;/span&gt;&lt;/span&gt;(&lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt;&lt;/span&gt;* &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;mem&lt;/span&gt;&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style="color: rgb(3, 0, 3);font-family:Courier New;font-size:85%;"  &gt;&lt;span style="color: rgb(3, 0, 3);font-family:'Courier New';font-size:10px;"  &gt;CompressionType&lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;  &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;getCompressionType&lt;/span&gt;&lt;/span&gt;(&lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;const&lt;/span&gt;&lt;/span&gt; &lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt;&lt;/span&gt; *&lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;mem&lt;/span&gt;&lt;/span&gt;,&lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;len&lt;/span&gt;&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;color:blue;"   &gt;&lt;span style=";font-family:'Courier New';font-size:10px;color:blue;"   &gt;const&lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt; &lt;span style="color:blue;"&gt;&lt;span style="color:blue;"&gt;char&lt;/span&gt;&lt;/span&gt;      *&lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;getCompressionTypeString&lt;/span&gt;&lt;/span&gt;(&lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;CompressionType&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(3, 0, 3);"&gt;&lt;span style="color: rgb(3, 0, 3);"&gt;type&lt;/span&gt;&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;div style="border-style: none none solid; padding: 0in 0in 1pt;"&gt; &lt;p class="MsoNormal" style="border: medium none ; padding: 0in;"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;};&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;This release supports four  open source compression libraries.  The CRYPTOPP implementation of GZIP,  MINILZO, ZLIB, and BZIP.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;This API simply supports  block memory compression and decompression.  You can compress a block of memory  using any one of the four compressors.  The compressed memory has a small header  on it that indicates which compressor was used, the size of the uncompressed  memory block, and a CRC so that it can easily and safely  decompressed.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;The test application, called  ‘test_compression’, loads a roughly 10mb XML file and runs it through each  compressor and decompressor and measures the performance characteristcs of  each.  The results are as follows:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:85%;"  &gt;&lt;span style=";font-family:Arial;font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;Testing Compression rate and  speed with various compressors.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;---------------------------------------------------------------&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;Compress:CT_CRYPTO  :FROM:  10,436,335 TO:  2,498,433   23%    1,170 MS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;Compress:CT_MINILZO :FROM:  10,436,335 TO:  3,940,072   37%       97 MS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;Compress:CT_ZLIB    :FROM:  10,436,335 TO:  3,299,771   31%      157 MS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;Compress:CT_BZIP    :FROM:  10,436,335 TO:  2,270,695   21%    1,544 MS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;---------------------------------------------------------------&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;Testing Decompression speed  with various decompressors.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;---------------------------------------------------------------&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;Decompress:CT_CRYPTO   :FROM:  2,498,433 TO: 10,436,335      258 MS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;Decompress:CT_MINILZO  :FROM:  3,940,072 TO: 10,436,335       42 MS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;Decompress:CT_ZLIB     :FROM:  3,299,771 TO: 10,436,335       69 MS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;Decompress:CT_BZIP     :FROM:  2,270,695 TO: 10,436,335      390 MS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;As expected, MINILZO is the  fastest.  Unfortunately MINILZO uses a GPL license and cannot be used in  commercial products.  The rest have licenses which are more flexible.  Check the  links for each package to see if it is right for you.  I did include the  ‘CryptoPP’ library for completeness though but, to be frank, I am not very  impressed with this package as the compression and decompression rates are very  poor.  As you would expect BZIP gets the best compression rate but does not  perform as quickly.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;I am fairly impressed with  ZLIB, especially because you can use it in a streaming mode as well, which is  excellent for network communications layers.  (FYI, the assembly language  version of the ZLIB decompressor is hardly any faster than the optimized C code  and was not included here.)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;You might wonder why I’m  even bothering to post this little snippet.  Beside the fact that I hope to save  other programmers a little bit of time in the future, I encourage any other  developers of compression libraries to drop them into this framework so we can  stop comparing apples to oranges when it comes to these technologies.  A large  XML file is a typical use case for the kind of data a game developer might want  to squeeze out some space savings for.  I am also happy to modify the installer  and include more standardized sample data if that is  relevant.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;I started to add in support  for the LZMA library, however they only offer a simple sample decompressor while  the compression code is a lot more difficult to extract into a single C style  API call.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;This demo comes with an easy  to use installer and a solution and project file for visual studio 2005.  All of  the compression code itself is multi-platform and only the little demo app makes  any OS specific calls.  The libraries are each included as raw source, each  located in their own directory.  None of the source has been removed (except for  test code) so you are not required to use the compression libraries via the  wrapper layer.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;If anyone feels compelled to  add additional compression libraries to this test framework please let me know  and I will make a point to include it in a new  drop.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;Thanks, I hope somebody  finds this useful.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style=";font-family:'Courier New';font-size:10px;"  &gt;John&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-7209995653585063067?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/compressiontest/' title='Compression / Decompression : Comparing Apples to Apples'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/7209995653585063067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=7209995653585063067' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/7209995653585063067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/7209995653585063067'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2008/03/compression-decompression-comparing.html' title='Compression / Decompression : Comparing Apples to Apples'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_PtTKwwh_xBc/R-mLZ8G7_SI/AAAAAAAADiU/grsmikJcb14/s72-c/1807117807_6ade84c3af.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-2925831763995433468</id><published>2008-03-13T09:41:00.000-07:00</published><updated>2008-03-13T09:58:08.217-07:00</updated><title type='text'>Spatial Awareness System</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_PtTKwwh_xBc/R9laDBN40BI/AAAAAAAADh8/brED7dm2SFw/s1600-h/41_pics_82664.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_PtTKwwh_xBc/R9laDBN40BI/AAAAAAAADh8/brED7dm2SFw/s400/41_pics_82664.jpg" alt="" id="BLOGGER_PHOTO_ID_5177268254551887890" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is the first release of my&lt;a href="http://www.amillionpixels.us/SAS_1.0.exe"&gt; Spatial Awareness System&lt;/a&gt; on March 13, 2008.  (The download is small (200k) and includes a basic installer.)&lt;br /&gt;&lt;br /&gt;A 'Spatial Awareness System' is a tool which keeps track of relationships between a large collection of objects represented by 3d co-ordinates (as floats).&lt;br /&gt;&lt;br /&gt;The typical use for a spatial awareness system (SAS) is for AI and network traffic culling. In AI you may have a limited range that the entity is supposed to be aware of.  Take for example a gun turret with a limited sight distance.  The awarness system will automatically collect the set of objects which are within this range.  The AI code can either iterate over this awareness list directly or respond to discrete events when objects come into and out of the awareness range.&lt;br /&gt;&lt;br /&gt;For network traffic you may want to reduce bandwidth by only transmitting packets for objects that are within a certain distance relative to other objects in the world.&lt;br /&gt;&lt;br /&gt;To use the spatial awareness system simply #include the file 'spatial_awareness_system.h'&lt;br /&gt;&lt;br /&gt;Spin up an instance of a spatial awareness system by using the factory method.&lt;br /&gt;&lt;br /&gt;Example:  SPATIAL_AWARENESS_SYSTEM::SpatialAwarenessSystem *sas = SPATIAL_AWARENESS_SYSTEM::Factory::Create(strategy,this);&lt;br /&gt;&lt;br /&gt;'strategy' is one of three possible spatial awareness system implementations to choose from. They are:&lt;br /&gt;&lt;br /&gt;SAS_BRUTE_FORCE         : Implements the brute force N-squared approach where every object is compared to every other object each frame.  This is very slow and only used for testing purposes.&lt;br /&gt;&lt;br /&gt;SAS_LAZY_KDTREE         : Uses a KdTree to help maintain the awareness state.  It is called 'lazy' because the KdTree is only updated every 16 frames.  This can produce some infrequent false negatives but never false positives.&lt;br /&gt;&lt;br /&gt;SAS_SAP_SYSTEM          : Uses Pierre Terdiman's Sweep and Prune algorithm (&lt;a href="http://www.blogger.com/www.codercorner.com"&gt;www.codercorner.com&lt;/a&gt;) as the main engine for maintaining awareness.&lt;br /&gt;&lt;br /&gt;The 'this' pointer refers to an implementation of the SpatialAwarenessObserver pure virtual class that will receive event notifications as objects enter and leave awareness.&lt;br /&gt;&lt;br /&gt;The objects for which awareness is being maintained are referred to by a unique 64bit guid.  If you wish, you can cast an object pointer to this GUID if necessary.&lt;br /&gt;&lt;br /&gt;The test application is located in the directory 'SphereTest'.  Simply load 'SphereTest.sln' into Visual Studio.  (There is nothing windows specific about the code, other than the demo app,  and the spatial awareness system itself should theoretically compile and run on any OS.)&lt;br /&gt;&lt;br /&gt;After you build and run the application you can hit the 'R' key to toggle the visual display of the awareness data.  Rendering is disabled by default since simulations with extremely large object counts can take a long time to display.&lt;br /&gt;&lt;br /&gt;Pressing the 'M' key will write out a text file called 'sas_memory.txt' that shows all memory allocations performed by the current SAS&lt;br /&gt;&lt;br /&gt;Press ESC to exit the application.&lt;br /&gt;&lt;br /&gt;The command line argument passed in controls the number of objects to be simulated.  A maximum of 65535 objects are allowed.  For real-time visualization it is best to keep the count under 2,000 otherwise rendering is too slow and the number of connections fill the screen.  Simulations on the order of tens of thousands of moving objects runs surprisingly fast.  Objects with an awareness range of zero do not maintain awareness of other entities, yet, other entities are aware of it.&lt;br /&gt;&lt;br /&gt;To experiment with the demo program you need to load the file 'ENTITY.CPP' and make some small code changes.&lt;br /&gt;&lt;br /&gt;The first #define EVENT_BASED controls whether the objects are rendered by iterating the awareness, or by tracking create/delete events.  Iteration is much faster but the option is there to debug that all of the create/delete events are being handled correctly.&lt;br /&gt;&lt;br /&gt;The next #define ALLOW_DELETES controls whether objects are constantly created and deleted.&lt;br /&gt;&lt;br /&gt;The next line defines which of the three SAS strategies to employ.&lt;br /&gt;&lt;br /&gt;The #define LIFETIME controls the random lifespan given to objects which are being created/deleted.&lt;br /&gt;&lt;br /&gt;I would consider this kind of alpha software at this point.&lt;br /&gt;&lt;br /&gt;The brute force and lazy kdtree versions seem to be stable and work correctly in all test conditions.&lt;br /&gt;&lt;br /&gt;The Lazy KdTree is fairly high performance and doesn't have performance or memory issues except in pathological cases where every object is nearly aware of every other object.&lt;br /&gt;&lt;br /&gt;The sweep and prune implementation appears stable, high performance, and has a reasonable memory footprint.  In this release, there appears to be a glitch or two when object deletions are enabled.  I am still tracking this down.&lt;br /&gt;&lt;br /&gt;The reason I am releasing this code is because, first it is built upon some other open source code and I felt it only fair to make it available.  The second, and most important reason, is that I am looking for feedback, bug fixes, improvements, suggestions, and anything else I can learn from the rest of the development community on solving this particular problem.&lt;br /&gt;&lt;br /&gt;For questions or feedback, please write to:&lt;br /&gt;&lt;br /&gt;John W. Ratcliff&lt;br /&gt;&lt;a href="mailto:%20jratcliff@infiniplex.net"&gt;mailto: jratcliff@infiniplex.net&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-2925831763995433468?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/SAS_1.0.exe' title='Spatial Awareness System'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/2925831763995433468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=2925831763995433468' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2925831763995433468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/2925831763995433468'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2008/03/spatial-awareness-system.html' title='Spatial Awareness System'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_PtTKwwh_xBc/R9laDBN40BI/AAAAAAAADh8/brED7dm2SFw/s72-c/41_pics_82664.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-1413831154806519025</id><published>2008-01-10T13:13:00.000-08:00</published><updated>2008-01-12T22:28:38.559-08:00</updated><title type='text'>FIRST Robotics</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_PtTKwwh_xBc/R4aKxb_uzwI/AAAAAAAADSM/5LXdKK2VBAk/s1600-h/FIRSTlogoR_color_rgb.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_PtTKwwh_xBc/R4aKxb_uzwI/AAAAAAAADSM/5LXdKK2VBAk/s400/FIRSTlogoR_color_rgb.jpg" alt="" id="BLOGGER_PHOTO_ID_5153959405505400578" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;My son, Alex, is a freshman in high school and just joined the FIRST robotics team.  The robotics team is right now in the big competition season rush.  I really cannot understand why they only give these guys six weeks to produce a complex robot but that is what the rules are.&lt;br /&gt;&lt;br /&gt;I have decided to help out the team by mentoring students who are focused on computer programming.  Since I already have a coding snippets website, I look forward to posting some snippets of robot control code here in the future.&lt;br /&gt;&lt;br /&gt;Right now I'm just getting my feet wet trying to understand the whole development environment process for the robotics controller but once I get the hang of it I hope to be doing some innovative stuff soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-1413831154806519025?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/1413831154806519025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=1413831154806519025' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1413831154806519025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1413831154806519025'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2008/01/first-robotics.html' title='FIRST Robotics'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_PtTKwwh_xBc/R4aKxb_uzwI/AAAAAAAADSM/5LXdKK2VBAk/s72-c/FIRSTlogoR_color_rgb.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-5473116439749169411</id><published>2008-01-02T11:08:00.000-08:00</published><updated>2008-01-03T14:20:21.348-08:00</updated><title type='text'>DFRAC alpha release : An Interactive Mandelbrot Explorer Program</title><content type='html'>&lt;a href="http://bp2.blogger.com/_PtTKwwh_xBc/R3vgY7_uzuI/AAAAAAAADR8/VrLe7QKQ02Y/s1600-h/dfrac10.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5150957317854777058" style="" alt="" src="http://bp2.blogger.com/_PtTKwwh_xBc/R3vgY7_uzuI/AAAAAAAADR8/VrLe7QKQ02Y/s400/dfrac10.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Over the holidays I worked on a &lt;a href="http://en.wikipedia.org/wiki/Mandelbrot_set"&gt;Mandelbrot &lt;/a&gt;exploration program. This is an alpha-pre-release. It requires a Windows machine with DirectX 9 to run. You may not be able to see the 3d graphics view on some older graphics cards. You can install the program using this link. It is only a 2mb installer. This does include source code, but much more work is expected to be done on it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/Dfrac_1.0.exe"&gt;Dfrac_1.0.exe&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can read the documentation online at this link: &lt;a href="http://www.amillionpixels.us/Dfrac.htm"&gt;Dfrac.htm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here are some screenshots from the program, showing some 3d and 2d views.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp1.blogger.com/_PtTKwwh_xBc/R3vgUr_uztI/AAAAAAAADR0/05yvOwvMrO4/s1600-h/montage.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5150957244840333010" style="" alt="" src="http://bp1.blogger.com/_PtTKwwh_xBc/R3vgUr_uztI/AAAAAAAADR0/05yvOwvMrO4/s400/montage.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://bp0.blogger.com/_PtTKwwh_xBc/R3vgMb_uzsI/AAAAAAAADRs/TDCPSXr2FHw/s1600-h/dfrac11.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5150957103106412226" style="" alt="" src="http://bp0.blogger.com/_PtTKwwh_xBc/R3vgMb_uzsI/AAAAAAAADRs/TDCPSXr2FHw/s400/dfrac11.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://bp2.blogger.com/_PtTKwwh_xBc/R3vgI7_uzrI/AAAAAAAADRk/-xDtx2eFG6A/s1600-h/dfrac7.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5150957042976870066" style="" alt="" src="http://bp2.blogger.com/_PtTKwwh_xBc/R3vgI7_uzrI/AAAAAAAADRk/-xDtx2eFG6A/s400/dfrac7.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://bp0.blogger.com/_PtTKwwh_xBc/R3vgEb_uzqI/AAAAAAAADRc/uh3uYrslveo/s1600-h/dfrac8.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5150956965667458722" style="" alt="" src="http://bp0.blogger.com/_PtTKwwh_xBc/R3vgEb_uzqI/AAAAAAAADRc/uh3uYrslveo/s400/dfrac8.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://bp0.blogger.com/_PtTKwwh_xBc/R3vf-b_uzpI/AAAAAAAADRU/Uj46x1QLCWQ/s1600-h/dfrac6.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5150956862588243602" style="" alt="" src="http://bp0.blogger.com/_PtTKwwh_xBc/R3vf-b_uzpI/AAAAAAAADRU/Uj46x1QLCWQ/s400/dfrac6.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://bp1.blogger.com/_PtTKwwh_xBc/R3vf5r_uzoI/AAAAAAAADRM/xpemb1-rre4/s1600-h/dfrac4.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5150956780983864962" style="" alt="" src="http://bp1.blogger.com/_PtTKwwh_xBc/R3vf5r_uzoI/AAAAAAAADRM/xpemb1-rre4/s400/dfrac4.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://bp2.blogger.com/_PtTKwwh_xBc/R3vf17_uznI/AAAAAAAADRE/3RfMK-jn6lA/s1600-h/dfrac3.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5150956716559355506" style="" alt="" src="http://bp2.blogger.com/_PtTKwwh_xBc/R3vf17_uznI/AAAAAAAADRE/3RfMK-jn6lA/s400/dfrac3.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-5473116439749169411?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/Dfrac.htm' title='DFRAC alpha release : An Interactive Mandelbrot Explorer Program'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/5473116439749169411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=5473116439749169411' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/5473116439749169411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/5473116439749169411'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2008/01/dfrac-alpha-release-interctive.html' title='DFRAC alpha release : An Interactive Mandelbrot Explorer Program'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_PtTKwwh_xBc/R3vgY7_uzuI/AAAAAAAADR8/VrLe7QKQ02Y/s72-c/dfrac10.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-6983533649548223012</id><published>2007-08-01T13:26:00.000-07:00</published><updated>2007-08-01T13:38:07.538-07:00</updated><title type='text'>Fast A*Star implemenation by Justin Heyes-Jones</title><content type='html'>&lt;a href="http://bp1.blogger.com/_PtTKwwh_xBc/RrDs17-8rAI/AAAAAAAAAvU/V_E_PZFbxt0/s1600-h/2006-1025star.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5093831589934967810" style="CURSOR: hand" alt="" src="http://bp1.blogger.com/_PtTKwwh_xBc/RrDs17-8rAI/AAAAAAAAAvU/V_E_PZFbxt0/s400/2006-1025star.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Justin Heyes-Jones has a great implemenation of the AStar path finding algorithm on the Internet. He is an AI enthusiast and has contributed a lot of resources to the development community. You can find his &lt;a href="http://www.geocities.com/jheyesjones/astar.html"&gt;website here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;When I decided to evaluate Justin's Astar implementation I found nothing wrong with it and went ahead and did a full integration. The only thing I did change was to make a wrapper interface around his heavily templated class. This is purely a matter of programming style. I like to use pure-virtual interfaces wherever possible and hide the implementation details behind a set of simple C calls using the PIMPLE paradigm (pointer to implementation).&lt;br /&gt;&lt;br /&gt;My wrapper is prototyped in the following simple header file: &lt;a href="http://www.amillionpixels.us/FastAstar.h"&gt;FastAstar.h&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The implementation which includes two template classes by Justin embedded as well as my own wrapper code can be found here: &lt;a href="http://www.amillionpixels.us/FastAstar.cpp"&gt;FastAstar.cpp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Justin uses a fast allocator template when implementing the Astar algorithm and the performance is extraordinarily fast.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-6983533649548223012?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.geocities.com/jheyesjones/astar.html' title='Fast A*Star implemenation by Justin Heyes-Jones'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/6983533649548223012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=6983533649548223012' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/6983533649548223012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/6983533649548223012'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/08/fast-astar-implemenation-by-justin.html' title='Fast A*Star implemenation by Justin Heyes-Jones'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_PtTKwwh_xBc/RrDs17-8rAI/AAAAAAAAAvU/V_E_PZFbxt0/s72-c/2006-1025star.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-5754999441145192191</id><published>2007-06-16T13:32:00.000-07:00</published><updated>2007-06-16T13:40:03.503-07:00</updated><title type='text'>MeshCleanup</title><content type='html'>&lt;a href="http://bp1.blogger.com/_PtTKwwh_xBc/RnRJoUwWTQI/AAAAAAAAAg0/SxjlB36vesc/s1600-h/damagecontrol.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5076763637068483842" style="CURSOR: hand" alt="" src="http://bp1.blogger.com/_PtTKwwh_xBc/RnRJoUwWTQI/AAAAAAAAAg0/SxjlB36vesc/s400/damagecontrol.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This post presents a generally useful code snippet.  It deals with a fairly common problem of trying to clean up a potentially bad triangle mesh.  Here is what it does:&lt;br /&gt;&lt;br /&gt;(1) Detects duplicate triangles and removes them.&lt;br /&gt;(2) Detects degenerate triangles and removes them.&lt;br /&gt;(3) Detects double sided triangles and extrudes them into a solid shape.&lt;br /&gt;&lt;br /&gt;The implementation is fast because it uses a hash_map to avoid having to iterate comparing every triangle winding order to every other triangle.&lt;br /&gt;&lt;br /&gt;Simply pass it an indexed triangle mesh in and you get a cleaned up indexed triangle mesh back out.&lt;br /&gt;&lt;br /&gt;Here is the source:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/MeshCleanup.h"&gt;MeshCleanup.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/MeshCleanup.cpp"&gt;MeshCleanup.cpp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It requires a few of the snippets previously uploaded to compile.  They are:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/VertexLookup.h"&gt;VertexLookup.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/VertexLookup.cpp"&gt;VertexLookup.cpp&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.h"&gt;FloatMath.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.cpp"&gt;FloatMath.cpp&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/IntPtr.h"&gt;IntPtr.h&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-5754999441145192191?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/5754999441145192191/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=5754999441145192191' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/5754999441145192191'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/5754999441145192191'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/06/meshcleanup.html' title='MeshCleanup'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_PtTKwwh_xBc/RnRJoUwWTQI/AAAAAAAAAg0/SxjlB36vesc/s72-c/damagecontrol.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-7672696216148358134</id><published>2007-06-16T13:12:00.000-07:00</published><updated>2007-06-16T13:16:21.684-07:00</updated><title type='text'>FloatMath revisited</title><content type='html'>&lt;a href="http://bp1.blogger.com/_PtTKwwh_xBc/RnREYUwWTPI/AAAAAAAAAgs/oEjNfvgv26c/s1600-h/SuitsFloating.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5076757864632438002" style="CURSOR: hand" alt="" src="http://bp1.blogger.com/_PtTKwwh_xBc/RnREYUwWTPI/AAAAAAAAAgs/oEjNfvgv26c/s400/SuitsFloating.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ever since I started doing this snippets thing I have been creating a floating point math library that does not have dependencies on any templates or classes.  This library uses a flat C style interface and accepts only float pointers as inputs and outputs.&lt;br /&gt;&lt;br /&gt;This library has not been created for completeness or thoroughness.  Instead, I am adding one routine to it at a time on an as needed basis.  As it grows it is slowly becoming an awesome reference implementation for lots of common basic math operations.&lt;br /&gt;&lt;br /&gt;I will be sure to keep updating it as time goes on.  Here is the latest incarnation.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.h"&gt;FloatMath.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FloatMath.cpp"&gt;FloatMath.cpp&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-7672696216148358134?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/7672696216148358134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=7672696216148358134' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/7672696216148358134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/7672696216148358134'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/06/floatmath-revisited.html' title='FloatMath revisited'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_PtTKwwh_xBc/RnREYUwWTPI/AAAAAAAAAgs/oEjNfvgv26c/s72-c/SuitsFloating.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-1040392307971613800</id><published>2007-06-16T13:05:00.000-07:00</published><updated>2007-06-16T13:12:07.070-07:00</updated><title type='text'>Vertex Lookup Revisited</title><content type='html'>&lt;a href="http://bp2.blogger.com/_PtTKwwh_xBc/RnRDCkwWTOI/AAAAAAAAAgk/HecUPFnVmAY/s1600-h/scarlett_johansson_fhm_top_7_big-751708.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5076756391458655458" style="CURSOR: hand" alt="" src="http://bp2.blogger.com/_PtTKwwh_xBc/RnRDCkwWTOI/AAAAAAAAAgk/HecUPFnVmAY/s400/scarlett_johansson_fhm_top_7_big-751708.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I made a post about this previously on this web log.   After making my original post I received some feedback about some problems with my approach. &lt;br /&gt;&lt;br /&gt;I believe I have no addressed those issues and I am uploading a new implementation.  It shares the same API but is implemented in a completely different way.&lt;br /&gt;&lt;br /&gt;The purpose of this routine is to weld vertices together when building an indexed triangle list.  The brute force way to do this is to iterate through all previously defined vertices and measure the distance to each and return as matching only those vertices which are within the distance threshold supplied.  My previous technique of using delta x, delta y, and delt z, comparisons does not entirely work doe to certain edge conditions.  The only valid way is to perform a true range based search.&lt;br /&gt;&lt;br /&gt;Since this is exactly what a Kd-Tree does, this new implementation uses a Kd-Tree to compute the array indices.  I have been using it this past week on some heavy duty meshing code and I am confident that this takes care of all edge conditions.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/VertexLookup.h"&gt;VertexLookup.h&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/VertexLookup.cpp"&gt;VertexLookup.cpp&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-1040392307971613800?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/1040392307971613800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=1040392307971613800' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1040392307971613800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1040392307971613800'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/06/vertex-lookup-revisited.html' title='Vertex Lookup Revisited'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_PtTKwwh_xBc/RnRDCkwWTOI/AAAAAAAAAgk/HecUPFnVmAY/s72-c/scarlett_johansson_fhm_top_7_big-751708.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-1708927824200999797</id><published>2007-06-16T12:49:00.000-07:00</published><updated>2007-06-16T13:01:55.419-07:00</updated><title type='text'>KdTree for fast range searching</title><content type='html'>&lt;a href="http://bp2.blogger.com/_PtTKwwh_xBc/RnQ_OkwWTNI/AAAAAAAAAgc/AGTTTCwZwWs/s1600-h/bunnykd.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5076752199570574546" style="CURSOR: hand" alt="" src="http://bp2.blogger.com/_PtTKwwh_xBc/RnQ_OkwWTNI/AAAAAAAAAgc/AGTTTCwZwWs/s400/bunnykd.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There are a lot of sources on the Internet for &lt;a href="http://www.google.com/search?sourceid=navclient&amp;ie=UTF-8&amp;amp;rls=GGLG,GGLG:2005-44,GGLG:en&amp;q=Kd%2dTree"&gt;Kd-Trees&lt;/a&gt; and here is just one more.   I don't suppose there is anything all that special about my Kd-Tree implemenation but if you just need one ready made, go ahead and use it.&lt;br /&gt;&lt;br /&gt;I don't support removing objects from the tree.  I will have to do some research on that.  A Kd-Tree can be built pretty fast though and, in the past, I have just rebuilt them from time to time to take into account changes.&lt;br /&gt;&lt;br /&gt;Kd-Trees are an ideal data structure for fast range searching.   One important note when building a Kd-Tree is that you should insert your nodes more or less at random if they might possible have any ordering in them to begin with.&lt;br /&gt;&lt;br /&gt;This Kd-Tree implementation is hard coded for three dimensions of space.  To declare it you simply would do the following:&lt;br /&gt;&lt;br /&gt;KdTree mTree;&lt;br /&gt;&lt;br /&gt;To add elements to it you simply would do as follows:&lt;br /&gt;&lt;br /&gt;mTree.add(x,y,z,radius,myData);&lt;br /&gt;&lt;br /&gt;The 'radius' represents the radius of the object you are inserting.  For a point, just set it to zero.  This first upload doesn't do anything with the radius yet, but I will revise it later.&lt;br /&gt;&lt;br /&gt;The 'userData' is a pointer to the object that is being represented or you could cast an integer if it represents an array index.&lt;br /&gt;&lt;br /&gt;To find the closest object to a point call 'getNearest'.&lt;br /&gt;&lt;br /&gt;To find the N number of closes points, in sorted order, call 'search'.&lt;br /&gt;&lt;br /&gt;Here is the implementation.  &lt;a href="http://www.amillionpixels.us/KdTree.h"&gt;KdTree.h&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-1708927824200999797?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://en.wikipedia.org/wiki/Kd-tree' title='KdTree for fast range searching'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/1708927824200999797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=1708927824200999797' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1708927824200999797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/1708927824200999797'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/06/kdtree-for-fast-range-searching.html' title='KdTree for fast range searching'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_PtTKwwh_xBc/RnQ_OkwWTNI/AAAAAAAAAgc/AGTTTCwZwWs/s72-c/bunnykd.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-8932628470686828678</id><published>2007-06-16T12:35:00.000-07:00</published><updated>2007-06-16T12:48:07.664-07:00</updated><title type='text'>Hash Map stdext::hash_map</title><content type='html'>&lt;a href="http://bp0.blogger.com/_PtTKwwh_xBc/RnQ7rEwWTMI/AAAAAAAAAgU/IWOP0QelNnU/s1600-h/untitled.bmp"&gt;&lt;img id="BLOGGER_PHOTO_ID_5076748291150335170" style="CURSOR: hand" alt="" src="http://bp0.blogger.com/_PtTKwwh_xBc/RnQ7rEwWTMI/AAAAAAAAAgU/IWOP0QelNnU/s400/untitled.bmp" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I know I haven't posted anything in a while; what can I say, I've been busy.  Recently I had to turn in a deadline for a book chapter in &lt;a href="http://www.introgamedev.com/cfp.html"&gt;AI Wisdom 4&lt;/a&gt;.  In doing so I wrote a few new snippets and I thought I would take this afternoon to publish them.&lt;br /&gt;&lt;br /&gt;The first snippet is just a simple template class that demonstrates the most common usage of an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;STL&lt;/span&gt; hash_map.  Semantically a hash_map works pretty much just like a regular &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;STL&lt;/span&gt; map but instead of using a red-black tree it maintains a hash table which allows most &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;lookups&lt;/span&gt; to be retrieved in a single step.  So long as you don't need to retain a specific ordering for a container, simply needing fast random access, then a hash_map is always the best way to go.&lt;br /&gt;&lt;br /&gt;Pretty much the most common usage of a hash_map is to associate some integer key (often a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;GUID&lt;/span&gt;) with a pointer to a class.  I made a small template that implements this most common usage in a fairly simple &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;API&lt;/span&gt;.  It is called '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;IntPtr&lt;/span&gt;'.&lt;br /&gt;&lt;br /&gt;For example, if you wanted to map a set of integers to a set of pointers to a class called 'Foo' you would declare it as follows:&lt;br /&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;IntPtr&lt;/span&gt;&lt;&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;mFooHash&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;To look up an instance of class Foo by a value you would say:  Foo *f = &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;mFooHash&lt;/span&gt;.get(v);&lt;br /&gt;To make an association between a Foo pointer and an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;interger&lt;/span&gt; it would be:&lt;br /&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;mFooHash&lt;/span&gt;.set(foo,v);&lt;br /&gt;&lt;br /&gt;To iterate the container you would say:&lt;br /&gt;&lt;br /&gt;Foo *f = &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;mFooHash&lt;/span&gt;.begin();&lt;br /&gt;while( f )&lt;br /&gt;{&lt;br /&gt;  f = &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;mFooHash&lt;/span&gt;.next();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;There is no &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_13"&gt;specific&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;destructor&lt;/span&gt; for this template and it assumes you own the memory &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_15"&gt;associated&lt;/span&gt; with the 'Foo' pointers.  You must remember to destruct them yourself.  There is another version of the template called '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;IntInt&lt;/span&gt;' which just provides a mapping between one integer type and another.&lt;br /&gt;&lt;br /&gt;I have been informed, by someone I trust knows what he is talking about, that you can use 64 bit long integers in an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;STL&lt;/span&gt; hash_map and they are &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_18"&gt;guaranteed&lt;/span&gt; to be unique.  This can be quite useful when associated very large &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;GUIDS&lt;/span&gt; with pointers to a class. &lt;br /&gt;&lt;br /&gt;If you have never messed around with the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;STL&lt;/span&gt; hash_map container this is a good place to begin experimenting with it.  It is a very powerful container and is extremely fast.&lt;br /&gt;&lt;br /&gt;Here is a link to the source and I will also update the repository page.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/intptr.h"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;intptr&lt;/span&gt;.h&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-8932628470686828678?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.introgamedev.com/cfp.html' title='Hash Map stdext::hash_map'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/8932628470686828678/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=8932628470686828678' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8932628470686828678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/8932628470686828678'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/06/hash-map-stdexthashmap.html' title='Hash Map stdext::hash_map'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_PtTKwwh_xBc/RnQ7rEwWTMI/AAAAAAAAAgU/IWOP0QelNnU/s72-c/untitled.bmp' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-319233840181652286</id><published>2007-04-17T11:18:00.000-07:00</published><updated>2007-04-17T11:29:58.166-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippets'/><category scheme='http://www.blogger.com/atom/ns#' term='Code Suppository'/><category scheme='http://www.blogger.com/atom/ns#' term='source code'/><category scheme='http://www.blogger.com/atom/ns#' term='CreateDynamics'/><title type='text'>The Code Suppository Repository</title><content type='html'>&lt;a href="http://bp3.blogger.com/_PtTKwwh_xBc/RiUP8qieHbI/AAAAAAAAAHY/K22yU1_-tZ0/s1600-h/obraz_DRZEWO.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5054463691678686642" style="CURSOR: hand" alt="" src="http://bp3.blogger.com/_PtTKwwh_xBc/RiUP8qieHbI/AAAAAAAAAHY/K22yU1_-tZ0/s400/obraz_DRZEWO.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Even though I like the idea of having a coding Blog it has become clear that this is a terrible way to actually provide software. &lt;br /&gt;&lt;br /&gt;I had to stay home from work this morning because we are getting new carpeting installed.  Since I had some free time I finally got around to a task I have been wanting to take care of for a long time.  Today I created &lt;a href="http://www.amillionpixels.us/sourcecode.htm"&gt;'The Code Suppository Repository'.&lt;/a&gt;  This is a simple web page that contains links to *current* versions of all of the code snippets I have posted on this blog.  I made sure that all of the links are current and hyperlinked each piece of &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_0"&gt;software&lt;/span&gt; with it's corresponding blog entry.  They are listed in chronological order as they appeared on this site.&lt;br /&gt;&lt;br /&gt;Probably the most important thing is that I revised every piece of source to be current with the latest versions I maintain for myself.  One question I had was what to do about the dead links the in the previous blog posts, or the posts which relate purely to earlier releases of software that are no longer relevant.  I have decided to just leave the blog the way it is but, from now on, always use the provided download page to get the latest version of anything.&lt;br /&gt;&lt;br /&gt;This was enough work just for today, but I fully intend to keep posting code snippets in the future.  Maybe I'm the only one who finds them valuable, I don't know, but &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_1"&gt;personally&lt;/span&gt; I couldn't get much done without my collection of 'snippets'.&lt;br /&gt;&lt;br /&gt;As for the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;CreateDynamics&lt;/span&gt; release.  I don't expect to see a new releases any time soon.  I don't have the bandwidth at this time.   Nevertheless, the release I have up here is functional to the extent that it demonstrates most of what I presented at &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;GDC&lt;/span&gt; and I think that is good enough for now.&lt;br /&gt;&lt;br /&gt;One final time, here is the permanent location for &lt;a href="http://www.amillionpixels.us/sourcecode.htm"&gt;'The Code Suppository Repository'&lt;/a&gt;.  Always use this to get the latest version of any code snippet or application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-319233840181652286?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/sourcecode.htm' title='The Code Suppository Repository'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/319233840181652286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=319233840181652286' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/319233840181652286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/319233840181652286'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/04/code-suppository-repository.html' title='The Code Suppository Repository'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_PtTKwwh_xBc/RiUP8qieHbI/AAAAAAAAAHY/K22yU1_-tZ0/s72-c/obraz_DRZEWO.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-3114001601964258635</id><published>2007-03-14T14:53:00.000-07:00</published><updated>2007-03-14T15:07:41.582-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='John Ratcliff'/><category scheme='http://www.blogger.com/atom/ns#' term='GDC 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='PhysXViewer'/><category scheme='http://www.blogger.com/atom/ns#' term='GDC'/><category scheme='http://www.blogger.com/atom/ns#' term='physics assets'/><category scheme='http://www.blogger.com/atom/ns#' term='game physics'/><category scheme='http://www.blogger.com/atom/ns#' term='CreateDynamics'/><title type='text'>New release of CreateDynamics with an installer</title><content type='html'>&lt;a href="http://bp3.blogger.com/_PtTKwwh_xBc/Rfhv_T9kDXI/AAAAAAAAAGU/CEfXUyu2TG8/s1600-h/Forest_road.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5041902916322200946" style="CURSOR: hand" alt="" src="http://bp3.blogger.com/_PtTKwwh_xBc/Rfhv_T9kDXI/AAAAAAAAAGU/CEfXUyu2TG8/s400/Forest_road.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I was finally able to scrape together of an installer for &lt;a href="http://www.amillionpixels.us/CreateDynamics_1.0.exe"&gt;CreateDynamics &lt;/a&gt;to go along with my GDC presentation. This is only a 7mb download with a full installer!&lt;br /&gt;&lt;br /&gt;Before you can run the executable you must have a recent version of &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=2DA43D38-DB71-4C1B-BC6A-9B6652CD92A3&amp;displaylang=en"&gt;DirectX 9.0 on your machine&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You must also have a copy of the &lt;a href="http://www.ageia.com/drivers/drivers.html"&gt;Ageia PhysX System Software&lt;/a&gt;. You can download it from their &lt;a href="http://www.ageia.com/drivers/drivers.html"&gt;site&lt;/a&gt;, or use this &lt;a href="http://www.amillionpixels.us/PhysX_6.12.02_SystemSoftware.exe"&gt;local link&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;To build the source you must have the &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=d625324c-59b4-4951-849e-640b508dc442&amp;amp;displaylang=en"&gt;October 2006 DirectX 9.0 SDK&lt;/a&gt; installed to the default directories.&lt;br /&gt;&lt;br /&gt;You must also have a copy of the &lt;a href="http://www.ageia.com/developers/downloads.html"&gt;Agiea PhysX SDK 2.4.4 or 2.7.0 installed&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I haven't provided a build configuration for 2.6 but all you have to do is change some include paths. The 2.7.0 SDK introduces the soft body feature and I am hopeful it will be part of the public release soon.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To extract and use just the CreateDynamics plugin and/or the ConvexDecomposition source library requires neither.&lt;br /&gt;&lt;br /&gt;Please read the release notes after you install.&lt;br /&gt;&lt;br /&gt;This demonstrates how to generate multiple collision model versions from a single art asset, including static representations, convex decomposition, ragdolls, fake softbodies, and pre-fracture assets.&lt;br /&gt;&lt;br /&gt;The tool needs a ton of features as well as bug fixes. It doesn't currently support cloth or tetrahderal soft bodies. The tetrahedral soft bodies are demonstrated in the 2.7.0 SDK release.&lt;br /&gt;&lt;br /&gt;I will update these as I make bug fixes and/or find the time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-3114001601964258635?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/CreateDynamics_1.0.exe' title='New release of CreateDynamics with an installer'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/3114001601964258635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=3114001601964258635' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3114001601964258635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3114001601964258635'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/03/new-release-of-createdynamics-with.html' title='New release of CreateDynamics with an installer'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_PtTKwwh_xBc/Rfhv_T9kDXI/AAAAAAAAAGU/CEfXUyu2TG8/s72-c/Forest_road.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-490665651750534201</id><published>2007-03-13T15:51:00.000-07:00</published><updated>2007-03-14T09:06:37.548-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='John Ratcliff'/><category scheme='http://www.blogger.com/atom/ns#' term='GDC 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='PhysXViewer'/><category scheme='http://www.blogger.com/atom/ns#' term='GDC'/><category scheme='http://www.blogger.com/atom/ns#' term='CreateDynamics'/><title type='text'>Update should be ready to release tomorrow</title><content type='html'>&lt;a href="http://bp3.blogger.com/_PtTKwwh_xBc/RfcrKj9kDWI/AAAAAAAAAGM/SkDlAbAoP7c/s1600-h/DCP_7702_0.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5041545768316702050" style="CURSOR: hand" alt="" src="http://bp3.blogger.com/_PtTKwwh_xBc/RfcrKj9kDWI/AAAAAAAAAGM/SkDlAbAoP7c/s400/DCP_7702_0.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Today I got the project revised so that it can generate the following versions of physics assets automatically:&lt;br /&gt;&lt;br /&gt;Raycast&lt;br /&gt;Static&lt;br /&gt;Dynamic&lt;br /&gt;Compound&lt;br /&gt;Fake Soft Body&lt;br /&gt;Pre-Fracture&lt;br /&gt;Ragdoll&lt;br /&gt;&lt;br /&gt;For now I do not have cloth and softbodies hooked back up again. If you want to play around with the soft body stuff, then just get the 2.7.0 SDK from Ageia and check out the sample application called 'PhysXViewer'.&lt;br /&gt;&lt;br /&gt;The only reason this drop isn't uploaded now is that I need to create an installer. The open-source component of this project is embedded within a much larger proprietary system that is being developed for my employer. In the past I have found it way too much of a hassle to manually extricate an open source build from this larger code base.&lt;br /&gt;&lt;br /&gt;Sometime tonight or tomorrow I will create an installer script that cherry picks only the open source components and will provide a proper installer with the basic features you would expect.&lt;br /&gt;&lt;br /&gt;This first drop is still a little rough around the edges but it does showcase the techniques I presented at GDC and is open source.&lt;br /&gt;&lt;br /&gt;Over the upcoming months I will continually refine the user interface and code base, as well as provide documentation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here are the slides. First as a small download, this contains just the slides and the exact spoken text of the talk in a Word Document file.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://aarm.mywowbb.com/~jratcliff/GDC2007_SMALL.zip"&gt;http://aarm.mywowbb.com/~jratcliff/GDC2007_SMALL.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To download the slides with the accompanying video clips use this link. Download size approx. 100mb&lt;br /&gt;&lt;br /&gt;&lt;a href="http://aarm.mywowbb.com/~jratcliff/GDC2007.zip"&gt;http://aarm.mywowbb.com/~jratcliff/GDC2007.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-490665651750534201?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/490665651750534201/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=490665651750534201' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/490665651750534201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/490665651750534201'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/03/update-should-be-ready-to-release.html' title='Update should be ready to release tomorrow'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_PtTKwwh_xBc/RfcrKj9kDWI/AAAAAAAAAGM/SkDlAbAoP7c/s72-c/DCP_7702_0.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-3936253107617722875</id><published>2007-03-12T08:56:00.000-07:00</published><updated>2007-03-12T09:01:39.483-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='John Ratcliff'/><category scheme='http://www.blogger.com/atom/ns#' term='GDC'/><category scheme='http://www.blogger.com/atom/ns#' term='CreateDynamics'/><category scheme='http://www.blogger.com/atom/ns#' term='Automatic Generation of Dynamics Models'/><title type='text'>I'm back from GDC</title><content type='html'>&lt;a href="http://bp1.blogger.com/_PtTKwwh_xBc/RfV4Uj9kDQI/AAAAAAAAAFY/nm5Ka-uuYk0/s1600-h/R3RP.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5041067652557311234" style="CURSOR: hand" alt="" src="http://bp1.blogger.com/_PtTKwwh_xBc/RfV4Uj9kDQI/AAAAAAAAAFY/nm5Ka-uuYk0/s400/R3RP.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I just got back from GDC.  My presentation went very well.  Even though it was the last talk on the last day, my room was completely full and people were standing all along the walls.  I was really pleased to find out that David Wu came to my talk, sat through the whole thing (which I presumed sounded like sitting in a Kindergarten class to him) and then even came up and gave me some personal feedback at the end!&lt;br /&gt;&lt;br /&gt;I number of people I know only via email and phone calls were there and I was really sorry I didn't have more time to chat with them.  Since my talk was on Friday, and my I was under major GDC crunch for my employer the week before, I ended up having to use almost all of my time at GDC working on my presentation.  I didn't finish it until 1pm the day of the talk!  I didn't get to see a single presentation the whole week and only breifly got to walk the show floor.&lt;br /&gt;&lt;br /&gt;In addition to getting my presentation done I felt it was really important to provide a new release of the CreateDynamics toolkit that would immedaitely show off everything I was talking about.  I got really close, but not quite all of the way.&lt;br /&gt;&lt;br /&gt;I hope to have a new upload sometime this week.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-3936253107617722875?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/3936253107617722875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=3936253107617722875' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3936253107617722875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3936253107617722875'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/03/im-back-from-gdc.html' title='I&apos;m back from GDC'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_PtTKwwh_xBc/RfV4Uj9kDQI/AAAAAAAAAFY/nm5Ka-uuYk0/s72-c/R3RP.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-458982427868380160</id><published>2007-03-05T08:25:00.000-08:00</published><updated>2007-03-05T08:34:59.910-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GDC'/><category scheme='http://www.blogger.com/atom/ns#' term='game physics'/><category scheme='http://www.blogger.com/atom/ns#' term='CreateDynamics'/><title type='text'>Heading to GDC</title><content type='html'>&lt;a href="http://bp1.blogger.com/_PtTKwwh_xBc/RexErTOuLRI/AAAAAAAAAFQ/DVuUEpk8qHg/s1600-h/27398.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5038477593807826194" style="CURSOR: hand" alt="" src="http://bp1.blogger.com/_PtTKwwh_xBc/RexErTOuLRI/AAAAAAAAAFQ/DVuUEpk8qHg/s400/27398.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I'm heading out to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;GDC&lt;/span&gt; today.  I will be giving a presentation on Friday at 4pm about the work I have done on &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;CreateDynamics&lt;/span&gt;.  It is my intention to upload a new code drop by then.&lt;br /&gt;&lt;br /&gt;Unfortunately I have been equally busy at my job getting things ready for &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;GDC&lt;/span&gt; so I haven't had much time to work on the software.  The entire framework is getting completely &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;refactored&lt;/span&gt; using a plug-in architecture as well as taking advantage of Project Builder for build management.&lt;br /&gt;&lt;br /&gt;It is, in many respects, a lot better than any of my previous releases.  On the other hand, many things that used to work are now broken.   The code is all still there, but it has to get &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;refactored&lt;/span&gt; to fit into the new framework cleanly.&lt;br /&gt;&lt;br /&gt;Right now I plan to spend most of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;GDC&lt;/span&gt; week sitting in the speakers lounge working on both my presentation as well as the software upload.  If it turns out I am unable to get a new software drop out, then it will have to wait until I return from &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;GDC&lt;/span&gt; to get it uploaded.&lt;br /&gt;&lt;br /&gt;I am hopeful I will be able to get this new version released this week and quickly follow up with some improvements going forward.  I will explore the idea of setting up a 'Source Forge' page to make it easier for people to locate code drops.&lt;br /&gt;&lt;br /&gt;Thanks,&lt;br /&gt;&lt;br /&gt;John W. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;Ratcliff&lt;/span&gt;&lt;br /&gt;Cell phone: 314-276-2180&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;Skype&lt;/span&gt; Phone: 636-486-4040&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;IM&lt;/span&gt; (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;skype&lt;/span&gt; preferred): &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;jratcliff&lt;/span&gt;63367&lt;br /&gt;Same handle applies for Yahoo and AOL &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;IM&lt;/span&gt;&lt;br /&gt;Email: &lt;a href="mailto:jratcliff@infiniplex.net"&gt;jratcliff@infiniplex.net&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-458982427868380160?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/458982427868380160/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=458982427868380160' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/458982427868380160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/458982427868380160'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/03/heading-to-gdc.html' title='Heading to GDC'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_PtTKwwh_xBc/RexErTOuLRI/AAAAAAAAAFQ/DVuUEpk8qHg/s72-c/27398.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-3568897299505608096</id><published>2007-02-02T19:28:00.000-08:00</published><updated>2007-02-22T08:16:19.440-08:00</updated><title type='text'>TinyXML</title><content type='html'>&lt;a href="http://bp3.blogger.com/_PtTKwwh_xBc/RcQBlZ18fGI/AAAAAAAAAA4/o1VT0Om1sLY/s1600-h/russ.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5027144826156252258" style="CURSOR: hand" alt="" src="http://bp3.blogger.com/_PtTKwwh_xBc/RcQBlZ18fGI/AAAAAAAAAA4/o1VT0Om1sLY/s400/russ.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Well, I made my previous post about the 'FileInterface' wrapper class but I don't think anyone understood why it was useful; so, I'm going to try again.&lt;br /&gt;&lt;br /&gt;This time I'm uploading the actual use-case I created it for.&lt;br /&gt;&lt;br /&gt;TinyXML is an absolutely awesome open-source 'code snippet'. You can find the &lt;a href="http://www.grinninglizard.com/tinyxml/"&gt;official site here.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is a modest amount of multi-platform source code, using no STL containers, that is robust, fast, stable, and provides an excellent way to load, modify, and save XML files. It doesn't support XREF's but, other than that, it is incredibly useful.&lt;br /&gt;&lt;br /&gt;The only problem I found with TinyXML is that it couldn't read or write to a buffer in memory. All of the code uses standard ANSI file-io routines ('fputc', 'fprintf', etc.). Rather than trying to dramatically modify the implementation I simply performed a global 'find-replace' on all of the file-io calls to revector them to my previously posted 'FileInterface' code snippet.&lt;br /&gt;&lt;br /&gt;This upload includes the modified TinyXML that uses the file interface routines. It will either read from a normal file like usual, or it will stream from a buffer in memory. I have also placed all of TinyXML in a namespace 'TINYXML' just to make sure it doesn't clash with any other code you might have in your application.&lt;br /&gt;&lt;br /&gt;Finally, I have included a small console application that will load an XML file using this technique and dump out the results using either a recursive or non-recursive descent of the nodes.&lt;br /&gt;&lt;br /&gt;Here is the link to the small download called &lt;a href="http://www.amillionpixels.us/TestTinyXML.zip"&gt;TestTinyXML.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This project is built with VC6 (yes, you heard me right VC6 is the only way to create code snippets) and you can happily auto-convert the workspace to VC7 or VC8. Of course, when you convert it to VC8 fucking Microsoft Studio will bitch at you and tell you that 'printf' AND ALL OTHER STANDARD ANSI C LIBRARY CALL are 'invalid'.&lt;br /&gt;&lt;br /&gt;Microsoft has a lot of nerve generating a warning message for a 'printf' statement.   I sometimes feel like I am the only programmer left in the world who cares about multi-platform and standard ANSI-C/C++ compatibility.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-3568897299505608096?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.grinninglizard.com/tinyxml/' title='TinyXML'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/3568897299505608096/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=3568897299505608096' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3568897299505608096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/3568897299505608096'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/02/tinyxml.html' title='TinyXML'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_PtTKwwh_xBc/RcQBlZ18fGI/AAAAAAAAAA4/o1VT0Om1sLY/s72-c/russ.JPG' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-681032529395247988</id><published>2007-02-01T14:39:00.000-08:00</published><updated>2007-02-01T14:45:54.895-08:00</updated><title type='text'>Reading .INI files</title><content type='html'>&lt;a href="http://bp3.blogger.com/_PtTKwwh_xBc/RcJsH518fFI/AAAAAAAAAAs/MyU3zaFD_V0/s1600-h/P041590e2_na_skle2.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5026699017140862034" style="CURSOR: hand" alt="" src="http://bp3.blogger.com/_PtTKwwh_xBc/RcJsH518fFI/AAAAAAAAAAs/MyU3zaFD_V0/s400/P041590e2_na_skle2.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I guess nobody downloaded my last code snippet because I didn't receive any emails telling me the link was bad.  I fixed a couple of typos and re-uploaded it.&lt;br /&gt;&lt;br /&gt;The snippets I am uploading today is something that programmers have to do all of the time which is to read and digest .INI files. &lt;br /&gt;&lt;br /&gt;A .INI file basically looks like this:&lt;br /&gt;&lt;br /&gt;[RENDER]&lt;br /&gt;option1=value1&lt;br /&gt;option2=value2&lt;br /&gt;[KEYBOARD]&lt;br /&gt;key1=value1&lt;br /&gt;key2=value2&lt;br /&gt;&lt;br /&gt;etc.&lt;br /&gt;&lt;br /&gt;There is usually a comment symbol such as ';' '!' or '#' which, if seen as the first non-whitespace character treats the whole line as a comment.&lt;br /&gt;&lt;br /&gt;In my implementation if you have [RENDER] then some other blocks and go back to [RENDER] again, it adds any new values to that.&lt;br /&gt;&lt;br /&gt;My implementation supports non-key value entries as well.&lt;br /&gt;&lt;br /&gt;[RENDER]&lt;br /&gt;This is some stuff I'm adding that isn't key value pair.&lt;br /&gt;key1=value1&lt;br /&gt;&lt;br /&gt;In this case the line of text 'This is some stuff..' would be returned as a key with no value.&lt;br /&gt;&lt;br /&gt;You can have spaces in your section headers, so [RENDER THIS THING] is a valid.&lt;br /&gt;&lt;br /&gt;One feature of my implmentation is that all of the return values point back to the original file so the pointers are completly persistent and you can take advantage of this by either caching the pointers, or at least passing them around and not worry that they will dissapear on you.&lt;br /&gt;&lt;br /&gt;Also, since the parser does no memory copies, it is extremely fast.  I can digest a many, many, megabyte .INI file virtually instantaneously.&lt;br /&gt;&lt;br /&gt;The implementation exports the functionality through simple C style function calls and opaque pointers.&lt;br /&gt;&lt;br /&gt;Here is the header file.  &lt;a href="http://www.amillionpixels.us/KeyValueIni.h"&gt;KeyValueIni.h&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The implementation includes an example program that shows how to call the routines and iterate on the data.  It is commented out with the pre-processor define TEST_MAIN.&lt;br /&gt;&lt;br /&gt;The implementation is located here as: &lt;a href="http://www.amillionpixels.us/KeyValueIni.cpp"&gt;KeyValueIni.cpp&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-681032529395247988?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/681032529395247988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=681032529395247988' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/681032529395247988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/681032529395247988'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/02/reading-ini-files.html' title='Reading .INI files'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_PtTKwwh_xBc/RcJsH518fFI/AAAAAAAAAAs/MyU3zaFD_V0/s72-c/P041590e2_na_skle2.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-116861950533315496</id><published>2007-01-12T08:21:00.000-08:00</published><updated>2007-02-01T14:38:54.095-08:00</updated><title type='text'>FileInterface : A useful code snippet</title><content type='html'>&lt;a href="http://photos1.blogger.com/x/blogger/1252/124/1600/646903/Mikey%2520baby%2520large%2520file.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/x/blogger/1252/124/400/423907/Mikey%2520baby%2520large%2520file.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here is a genuinely useful code snippet. The purpose of this code is to allow you to rapidly refactor a library that performs direct file-IO so that it can support reading and writing to and from a buffer in memory.&lt;br /&gt;&lt;br /&gt;The best way to describe its usefulness is in the case I used it for. I suppose many of your are familiar with &lt;a href="http://www.grinninglizard.com/tinyxml/"&gt;TinyXML&lt;/a&gt;. This is a superb open source XML parser that is very fast, stable, and robust.&lt;br /&gt;&lt;br /&gt;The only small problem with TinyXML is that is assumes you are loading a file from disk. However, often times your XML resource is simply something you have loaded into a buffer in memory.&lt;br /&gt;&lt;br /&gt;Using this code snippet 'FileInterface.h' you can rapidly refactor massive amounts of source code by performing a find replace on all of the STDIO file routines (fopen, fclose, fwrite, fread, fprintf etc.)&lt;br /&gt;&lt;br /&gt;The only routines you have to do additional work on is 'fopen'. The refactored fopen has an option for you to pass in a buffer in memory and a length. If you do not pass this in, then the interface will do standard file IO. If you do pass a buffer then all reads or writes will happen relative to that buffer.&lt;br /&gt;&lt;br /&gt;There is an additional option for write access whereby you can choose not pass a destination buffer but rather one will be allocated and grown for you.&lt;br /&gt;&lt;br /&gt;To access this feature you open the file with the option "wmem".&lt;br /&gt;&lt;br /&gt;Here is an example usage:&lt;br /&gt;&lt;br /&gt;FILE_INTERFACE *fph = fi_fopen("test", "wmem" );&lt;br /&gt;fi_fprintf(fph,"This is a test.");&lt;br /&gt;fi_fclose(fph);&lt;br /&gt;&lt;br /&gt;To retrieve the buffer that was created you call 'fi_getMemBuffer' before the file is closed.&lt;br /&gt;&lt;br /&gt;size_t len;&lt;br /&gt;void *mem = fi_getMemBuffer(fph,len);&lt;br /&gt;&lt;br /&gt;To read from a buffer in memory you would use this pattern:&lt;br /&gt;&lt;br /&gt;FILE_INTERFACE *fph = fi_fopen("test,", "rb", mem, len);&lt;br /&gt;&lt;br /&gt;To read from a file on disk, simply don't pass the memory buffer.&lt;br /&gt;&lt;br /&gt;I have found this snippet to be quite useful, I hope you do to.&lt;br /&gt;&lt;br /&gt;Here is the header file: &lt;a href="http://www.amillionpixels.us/FileInterface.h"&gt;FileInterface.h&lt;/a&gt;&lt;br /&gt;Here is the implementation: &lt;a href="http://www.amillionpixels.us/FileInterface.cpp"&gt;FileInterface.cpp&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-116861950533315496?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/116861950533315496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=116861950533315496' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116861950533315496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116861950533315496'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/01/fileinterface-useful-code-snippet.html' title='FileInterface : A useful code snippet'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-116853270018217800</id><published>2007-01-11T08:20:00.000-08:00</published><updated>2007-01-11T08:26:46.116-08:00</updated><title type='text'>Stupid Utility Program : FileCode</title><content type='html'>&lt;a href="http://photos1.blogger.com/x/blogger/1252/124/1600/34360/img_20_orig.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/x/blogger/1252/124/400/890219/img_20_orig.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I am uploading a remarkbly simple utility program that I had to re-write today. I have written this stupid utility so many times I can't remember and it annoys me that I have to keep doing it. I figure if I upload it here I won't have to search for a copy in the future.   It's only a few dozen lines of code, but that is a few dozen lines I don't want to have to write again.&lt;br /&gt;&lt;br /&gt;All this utility does is convert an arbitrary file into a character array as source code. This is useful if you have a program that needs access to a few files, but you don't want to distribute the files themselves. Instead you can just embed the files directly into the source code and the distributable can be self-contained.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FileCode.cpp"&gt;Here is the source&lt;/a&gt; that reads in an arbtrary file and outputs a source and header file for it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/FileCode.exe"&gt;Here is the utility&lt;/a&gt; as a console program.&lt;br /&gt;&lt;br /&gt;I wrote it this morning because I have a graphics library that needs access to a texture and a shader file but I didn't want to have to require them as data assets on disk.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-116853270018217800?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/FileCode.cpp' title='Stupid Utility Program : FileCode'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/116853270018217800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=116853270018217800' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116853270018217800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116853270018217800'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/01/stupid-utility-program-filecode.html' title='Stupid Utility Program : FileCode'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-116830669929877270</id><published>2007-01-08T17:35:00.000-08:00</published><updated>2007-01-08T17:38:19.313-08:00</updated><title type='text'>Minor Update for Erwin Coumans</title><content type='html'>&lt;a href="http://photos1.blogger.com/x/blogger/1252/124/1600/881685/2003-09-01--Looking%20up%20at%20Westminster%20Abbey%20-%20London.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/x/blogger/1252/124/400/829160/2003-09-01--Looking%2520up%2520at%2520Westminster%2520Abbey%2520-%2520London.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is a very minor update and uses the same link. I added support to import and export the results from CreateDynamics in COLLADA 1.4.1 format again per Erwin's request.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/production.zip"&gt;Here's the link.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-116830669929877270?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/production.zip' title='Minor Update for Erwin Coumans'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/116830669929877270/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=116830669929877270' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116830669929877270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116830669929877270'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2007/01/minor-update-for-erwin-coumans.html' title='Minor Update for Erwin Coumans'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-116744950692802309</id><published>2006-12-29T19:26:00.000-08:00</published><updated>2006-12-29T20:03:48.606-08:00</updated><title type='text'>A Major new release of the CreateDynamics library and PhysXViewer</title><content type='html'>&lt;a href="http://photos1.blogger.com/x/blogger/1252/124/1600/381050/Mount-Rainier-and-Lenticular-Cloud-Reflected-at-Sunset_-Washington.jpg"&gt;&lt;img style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://photos1.blogger.com/x/blogger/1252/124/320/947435/Mount-Rainier-and-Lenticular-Cloud-Reflected-at-Sunset_-Washington.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;This is a major new release of the CreateDynamics Toolkit and PhysXViewer that represents a significant code cleanup. The new &lt;/strong&gt;&lt;/span&gt;&lt;a href="http://www.amillionpixels.us/production.zip"&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;download &lt;/strong&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;is only 10mb and is complete; most of that 10mb is the binary executables, documentation, and a little bit of sample data&lt;/strong&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;!!!You cannot run this unless you have installed the PhysX SystemSoftware from Ageia!!!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;This requires at least version 6.12.02 or higher. If you don't already have the system software installed you can get it from the Ageia website or from this &lt;a href="http://www.amillionpixels.us/PhysX_6.12.02_SystemSoftware.exe"&gt;link&lt;/a&gt;. Sadly, while I got the build of CreateDynamics down to just 10mb, the system software is 22mb.&lt;br /&gt;&lt;br /&gt;Before I get into the contents of this upload I want to say a few things. First of all, I would like to announce that I no longer work for Ageia full time. I am still providing support, especially for the NxuStream serialization library, but the bulk of my time is going to be spent at my new job working for &lt;a href="http://www.play.net/"&gt;Simutronics &lt;/a&gt;on their &lt;a href="http://www.play.net/hj/"&gt;Hero Engine&lt;/a&gt;. My first projects will involve using the CreateDynamics tool kit to make 'physics ready' all of their game assets. I have loved working for Ageia but I have also been very anxious to actually incorporate all of this technology into an actual game. I still plan to be working closely with Ageia in the future to help assist them in deploying new technologies as they become available.&lt;br /&gt;&lt;br /&gt;The results of this project is going to be presented &lt;a href="http://www.gdconf.com/"&gt;at GDC 2007&lt;/a&gt; as a &lt;a href="https://www.cmpevents.com/GD07/a.asp?option=C&amp;V=11&amp;amp;SessID=3706"&gt;60 minute programming lecture.&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;I have removed the previous source drops from this site and everything you need is contained in this single download.&lt;br /&gt;&lt;br /&gt;One final personal note. While I am certainly having fun doing this project and I hope that it helps other programmers, if nothing else, as a learning aid, I do have a favor to ask. If you have a PayPal account please consider donating a few dollars to my son's youth group. He has a website to solicit donations (using the pay-for-a-pixel approach). In fact, all of the content for this project is hosted there.&lt;br /&gt;&lt;br /&gt;Please click on this link to &lt;a href="http://www.amillionpixels.us"&gt;A Million Pixels US&lt;/a&gt; Move your mouse over the page and find a spot that you would like to purchase. There are still many $4 spots left. If you are feeling generous, like Erwin Coumans was, consider making a larger donation. You will be recognized on the site and the blog for your generous donation. My son's youth group needs to raise funds for their charitable activities and various functions. Just last month the group held a large Thanksgiving feast for over 35 people as a show of gratitude and fellowship with the community. If you appreciate all of this great free source code please show a kindness and forward a few bucks his way.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This new version provides just some of the following:&lt;br /&gt;&lt;br /&gt;* An open source physics viewer called (PhysXViewer) that is built off of the DirectX 9.0 samples framework. This should be much easier to step through and understand.&lt;br /&gt;&lt;br /&gt;* The latest version of the NxuStream serialization library.&lt;br /&gt;&lt;br /&gt;* A source code library that demonstrates how to integrate NxuStream assets, skinned meshes, and softbodies into a game. Works through a set of pure virtual interfaces to allow you to easily adapt it to your own game engine.&lt;br /&gt;&lt;br /&gt;* Full soft body support with the 2.7.0 SDK release of PhysX. This SDK has not yet been released to the public so this functionality is conditionally compiled away. As soon as the SDK and system libraries are released the build will support the volumetric soft body feature.&lt;br /&gt;&lt;br /&gt;* The prototype 3D Studio Max plug-in of for convex decomposition is included in this build.&lt;br /&gt;&lt;br /&gt;* CreateDynamics has been revised to be able to auto-generate skinned meshes. It creates an inferred skeleton directly from a static mesh.&lt;br /&gt;&lt;br /&gt;* A bug was fixed in the convex decomposition library that improves the quality of the split meshes.&lt;br /&gt;&lt;br /&gt;* A skeleton pruning algorithm was implemented to better automate the processing of complex skeletal meshes to rag doll models.&lt;br /&gt;&lt;br /&gt;For more detailed information about the release here are some links to the documentation I have available.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/Documentation/ChangeList.htm"&gt;The ChangeList with a lot of detailed information about this release.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/Documentation/The%20NxuStream%20FAQ.htm"&gt;The NxuStream FAQ&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/Documentation/PhysXViewer.htm"&gt;The PhysXViewer documentation&lt;/a&gt; (note, mostly about the SoftBody feature not yet avaialble.)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/Documentation/The%20CreateDynamics%20Toolkit.htm"&gt;CreateDynamics documentation&lt;/a&gt; (quite a bit out of date but still useful.)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-116744950692802309?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/production.zip' title='A Major new release of the CreateDynamics library and PhysXViewer'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/116744950692802309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=116744950692802309' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116744950692802309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116744950692802309'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2006/12/major-new-release-of-createdynamics.html' title='A Major new release of the CreateDynamics library and PhysXViewer'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-116501479747375925</id><published>2006-12-01T15:00:00.000-08:00</published><updated>2006-12-01T15:15:55.800-08:00</updated><title type='text'>Auto-Generatd Skinned Meshes</title><content type='html'>&lt;a href="http://photos1.blogger.com/x/blogger/1252/124/1600/355303/goldy2.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/x/blogger/1252/124/400/827560/goldy2.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Well, I finally got around to working on my automatic skeletonization and skinning code.  You have seen my previously posted stuff on automatic convex decomposition.  Well, a week or so ago I had a day to spend on automatic skeletonization and it turned out really well!  I got amazing skeletons from my decompositions.  I won't describe the algorithm entirely here, especially since I will be presenting on it at GDC.  &lt;br /&gt;&lt;br /&gt;I did want to upload a video showing just one example of how it can work.  I have many test cases that all look very promising.  However, it takes quite a while to create a movie file so I am just uploading this one.&lt;br /&gt;&lt;br /&gt;On another point, I am creating a new sample application using DirectX that was built from the ground up.  No Rocket source code at all.  It will be an excellent learning tool and includes support for skeletal deformed meshes. &lt;br /&gt;&lt;br /&gt;In the video I am uploading here you see a chair that was originally just a basic WaveFront OBJ file and raw mesh.  I performed the convex decomposition on it, then inferred a skeleton.  Next I automatically generated a skinned mesh by inferring bone weightings to the nearest rigid bodies.   Finally, I let the simulation run and skinned the mesh based on the real-time simulation of the rigid bodies.&lt;br /&gt;&lt;br /&gt;In this example you see what started out as a solid chair but in the simulation it appears to have been turned into melted plastic.&lt;br /&gt;&lt;br /&gt;My thinking is that auto-generated skinned meshes against a constrained system can act as a 'poor-man's' soft body.  One of the big advantages is that all of the skinning happens on the GPU so your only limiting factor is solving the constraints and the rigid body collisions.  Of course, you also get self-collision pretty much for free.&lt;br /&gt;&lt;br /&gt;Additionaly the constraint limits and strengths could be modified in real-time to make objects stiffen up or melt away.&lt;br /&gt;&lt;br /&gt;Here is a link to the video clip as &lt;a href="http://www.amillionpixels.us/SoftChair.wmv"&gt;a WMV file&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-116501479747375925?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/SoftChair.wmv' title='Auto-Generatd Skinned Meshes'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/116501479747375925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=116501479747375925' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116501479747375925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116501479747375925'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2006/12/auto-generatd-skinned-meshes.html' title='Auto-Generatd Skinned Meshes'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-116319658912406020</id><published>2006-11-10T14:01:00.000-08:00</published><updated>2006-11-10T14:27:45.653-08:00</updated><title type='text'>Yet another Update for CreateDynamics</title><content type='html'>&lt;ul&gt;&lt;li&gt;&lt;a href="http://photos1.blogger.com/blogger/1252/124/1600/babel-brueghel-2.jpg"&gt;&lt;img style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/1252/124/400/babel-brueghel-2.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I am uploading a new drop of the &lt;a href="http://www.amillionpixels.us/CreateDynamics.zip"&gt;CreateDynamics toolkit&lt;/a&gt; primarily so that it is in sync with the latest tools plugins from Feeling Software. This version provides binaries both for the 2.4.4 PhysX SDK and the 2.6.2 PhysX SDK. The build configuration of the source code have been resivsed accordingly as well.&lt;br /&gt;&lt;br /&gt;There are also some minor bug fixes to NxuStream but nothing radical.&lt;br /&gt;&lt;br /&gt;I am planning on taking two weeks of vacation over Christmas so I can finally make some serious progress on some of the outstanding technology I want to develop.&lt;br /&gt;&lt;br /&gt;My primary goals are:&lt;br /&gt;&lt;br /&gt;Auto-generation of constrained systems based on a convex decomposition (effectively automatic skeletons)&lt;br /&gt;&lt;br /&gt;Auto-Generation of skinned meshes from static meshes with bone weighted bindings against the auto-generated skeleton. This will allow me to create a fake softbody system, similar to how a ragdoll works, in an automated fashion. The artist doesn't have to create a skeleton or create a deformed mesh. This will happen automatically.&lt;br /&gt;&lt;br /&gt;I want to finally get my 3d Studio Max plug-in version of the ConvexDecomposition code completed.&lt;br /&gt;&lt;br /&gt;I want to add support for creating closed meshes whenever I perform a split performing convex decompostion. This will fix outstanding bugs. It will increase stability. It will prevent the algorithm from generating hollow interiors. It will allow the tool to recurse much more deeply to find more exacting solutions.&lt;br /&gt;&lt;br /&gt;If want to implement a run-time library that automatically handles fractured models. This is different that using fixed joints for breaking. The library will 'listen' to the contact reports against the shapes in an object. If a contact is strong enough then that piece will be 'broken' off and let fly; the remaining shapes will be placed into a new actor. The piece that goes flying off will inherit the force from the original contact so that it will fly off realistically.&lt;br /&gt;&lt;br /&gt;The final piece in the puzzle is to auto-generate fracture *graphics*. This is a really tough problem and I may not have working for a while.&lt;br /&gt;&lt;br /&gt;It turns out that I have had a presentation accepted for the Game Developers Conference in March 2007. I have a 60 minute lecture about automatic generation of physics models. I want to get as much of this technology developed as possible over Christmas so that I can be fully prepared to make my talk.&lt;br /&gt;&lt;br /&gt;I will include the release notes I typed up for this version. The reason you haven't seen much in the way of major progess is that I have been working on a number of other projects at work. Currently I am writing some editing tools for an amazing piece of technology that I'm not sure I am allowed to talk about in public yet.&lt;br /&gt;&lt;br /&gt;---------------------------------------------------------------------&lt;br /&gt;&lt;strong&gt;CreateDynamics Changes with Release #8: November 10, 2006&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Changes:&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Revised version of NxuStream&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;Minor bug fixes, added support for soft bodies.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;New System Software installer compatible with 2.6.2&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;A new system softer installer ‘PhysX_6.11.01_SystemSoftware.exe’ was included so that this version can run against the latest SDK release.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;New executable folder and launch batch files.&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;The old executable folder ‘CreateDynamics’ still exists and runs against the 2.4.4 public release SDK.&lt;/li&gt;&lt;li&gt;A new executable folder has been created called ‘CreateDynamics262’ which contains binaries compatible with the 2.6.2 release of the PhysX SDK.&lt;/li&gt;&lt;li&gt;To run the 2.4.4 version of the modified rocket application launch ‘CreateDynamics.bat’&lt;/li&gt;&lt;li&gt;To run the 2.4.4 version of the PhysXViewer application (source code provided) run ‘PhysXViewer.bat’&lt;/li&gt;&lt;li&gt;To run the 2.6.2 version of the modified rocket application launch ‘CreateDynamics262.bat’&lt;/li&gt;&lt;li&gt;To run the 2.6.2 version of the PhysXViewer application (source code provided) run ‘PhysXViewer262.bat’&lt;/li&gt;&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;New build configurations&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;If you are a licensee and have access to the official 2.6.2 SDK then you can now build the PhysXViewer source code.  When you load the solution file \CreateDynamics\src\PhysXViewer\PhysXViewer.sln you will see that there are two new build configurations that target the 2.6.2 SDK.&lt;/li&gt;&lt;li&gt;The default ‘debug’ and ‘release’ configurations still target the 2.4.4 public SDK.&lt;/li&gt;&lt;li&gt;A Note about the PhysXViewer&lt;/li&gt;&lt;li&gt;The purpose of the PhysXViewer is to be an open source application that is the ‘official’ tool to view NxuStream data exported from Max, Maya, or from your own product.&lt;/li&gt;&lt;li&gt;Currently it can import NxuStream files in XML, binary, and COLLADA.&lt;br /&gt;I have been unable to spend the time on this tool that I would have liked.  It does not currently have mouse dragging, debug visualization, or graphics bindings.  These are fairly essential for this to be a usable tool.&lt;/li&gt;&lt;li&gt;You can run the CreateDynamics toolkit however and load and save data.&lt;/li&gt;&lt;li&gt;The reason the source is included is as a learning tool.  All of the source have now been placed in distinct libraries with minimal dependencies. &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-116319658912406020?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/CreateDynamics.zip' title='Yet another Update for CreateDynamics'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/116319658912406020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=116319658912406020' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116319658912406020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116319658912406020'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2006/11/yet-another-update-for-createdynamics.html' title='Yet another Update for CreateDynamics'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-116181807770979409</id><published>2006-10-25T16:11:00.000-07:00</published><updated>2006-10-25T16:14:37.720-07:00</updated><title type='text'>Some bug fixes to CreateDynamics and NxuStream</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/1252/124/1600/pumpksplash.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/1252/124/400/pumpksplash.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I had to upload a new build of CreateDynamics.zip because I found out I had broken the conversion to boxes, spheres, and capsules because of a few typos.  These are fixed now.  I also have revised to the latest version of NxuStream which compiles without warnings even in .NET 2005 and has a number of bug fixes.  I have had a QA team running a lot of data through it and it is getting better all of the time.&lt;br /&gt;&lt;br /&gt;If you are working the source code or downloaded the previous drop, I recommend you download this revision.  The link is the same, I have not been keeping previous builds online.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/CreateDynamics.zip"&gt;You can download the revision here.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-116181807770979409?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/CreateDynamics.zip' title='Some bug fixes to CreateDynamics and NxuStream'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/116181807770979409/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=116181807770979409' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116181807770979409'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116181807770979409'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2006/10/some-bug-fixes-to-createdynamics-and.html' title='Some bug fixes to CreateDynamics and NxuStream'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-116069215905376073</id><published>2006-10-12T14:57:00.000-07:00</published><updated>2006-10-12T15:45:22.620-07:00</updated><title type='text'>CreateDynamics and NxuStream update</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/1252/124/1600/kittygun.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/1252/124/400/kittygun.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I am uploading my first revision to NxuStream in about six weeks. Suprisingly the biggest change to this version is that the bulk of the NxuStream serialization code is now auto-generated. Once I finished the last version of NxuStream a few weeks ago I was suddenly faced with an enormous maintenence problem. (It is important to note that these changes were only to the internal implementation. The public interface did not change.)&lt;br /&gt;&lt;br /&gt;I inherited the original implementation from someone else and didn't think it would be the right thing to do to rewrite it from scratch. It turns out, had I done that, the whole thing would have taken a lot less time. In the end, with this release, none of the code from the very first original implementation remains. The code which streams data to and from either an XML or binary file was rewritten and is much cleaner.&lt;br /&gt;&lt;br /&gt;The biggest problem I faced was that this code is trying to serialize roughly 950 discrete data items. It also has to work across multiple versions of the SDK and take into account not only new features but also deprecated items or something as simple as a name change. The previous implementation did all of this maually. What I mean by that is a computer programmer had to write the load code, save code, import code and export code for every single data item as well as the complete constructor and destructor with all memory cleanup for every class. On top of that all of the enumerated values had to be able to be mapped to and from ASCII strings.&lt;br /&gt;&lt;br /&gt;If a single new data item had to be added this caused a programmer to have to manually change code in numerous source files. A single typo or oversight and the build would be broken or, more likely, simply be in error and no one would notice for a long time. Debugging these typos was exhausting and having to manually revise documentation more so.&lt;br /&gt;&lt;br /&gt;People who know me know that I am an impatient man. Once I started having to do this process myself I realized it was a losing proposition. I have better things to do with my life than manually maintain a bunch of source code that just does data manipulation and management.&lt;br /&gt;&lt;br /&gt;Now, as a game developer, I always try to find a data driven approach to a problem. This, however, was a bit different. I needed to generate an enormous amount of source code which had a certain degree of complexity and a lot of special cases. At first I took a look on the Internet for automatic code generators from an XML schema. While there are many products that do this (and it validated for me that this approach wasn't completely stupid) none of them were going to map to a highly customized API with a lot of special case situations.&lt;br /&gt;&lt;br /&gt;First I wrote a tool that could parse an XML schema and extract the data I needed. Since I already had an schema to begin with this gave me a good head start. Once I had extracted all of the data I needed I suddenly realized that I didn't have much use for the schema to begin with. Instead I built a comma seperated value spreadsheet that I could just edit manually in a text editor.&lt;br /&gt;&lt;br /&gt;The most difficult part after that was to scan through every header file to make 100% certain I had replicated every single data item perfectly. This was exhausting work but I was willing to do it because I knew it was something I would only have to do *one* time. Once I had my spreadsheet laid out I went about reading it in and turning it into code. I iterated on this for some weeks until it worked completely with all versions of the SDK. I even added automatic validation routines to so that if any of the serialization data in the SDK was out of sync with the implementation it would alert me immediately.&lt;br /&gt;&lt;br /&gt;I also had the tool auto-generate full doxygen compatible documentation as well as an XML schema file.&lt;br /&gt;&lt;br /&gt;The previous implementation used inheritance which proved to be a problem because the structures needed to read and write data to and from a file is not identical to the source. Mostly this problem was related to having to serialize pointers or containers. For this implementation I chose to use object mirroring. Every single class and enumeration in the NxuStream code base exists in its own namespace but still has the same identical name as the one it is replicating.&lt;br /&gt;&lt;br /&gt;The vast majority of the data can simply be copied automatically between the two mirrored items. In the cases where there was data that could not be copied automatically I wrote a piece of source code I called 'NXU_CustomCopy.cpp' that contains only the code necessary to replicate data items that couldn't be handled automatically. This is the only code I have to maintain manually now. I did spend a lot of time making the latest version be backwards compatible with the previous release. If you have existing content using the last release you should still be able to load it with this build. Read the release notes for more information about this.&lt;br /&gt;&lt;br /&gt;Going forward, now that this system is complete, I can rest assured that there will never be any memory leaks. There will never be a case where a typo calls an item to either load of save incorrectly. There will never be any data items that I 'forgot' to copy. In the future, when a new data item gets added to the SDK, I will (in almost all cases) simply have to update the data template and regenerate the code; having complete assurance that it all works perfectly.&lt;br /&gt;&lt;br /&gt;Putting this to bed now allows me to work on the things I really want to work on. These include the PhysXViewer (which I intend to become the 'official' viewer for NxuStream data and COLLADA physics). I want to improve the convex decomposition library to make closed surfaces whenever it does a split. This will fix an outstanding bug and produce better hulls. It will also get me one important step closer to auto-generating fracture geometry. I still want to use the results of the convex decomposition library to automatically generate a constrained system to do a form of inexpensive soft-body; where the model is simulated with a rigid body engine but skinned using a GPU. And, of course, I want to do more work with the GrannyPhysX integration to demonstrate how to attach cloth to characters and do physically driven character animation.&lt;br /&gt;&lt;br /&gt;I added a new application with this release that shows how to use the CreateDynamics toolkit directly in your own plug-in as source code. It also provides shell source to demonstrate how to make it process data directly from your own engine.&lt;br /&gt;&lt;br /&gt;Here is some of the documentation with further details about this and previous releases. This documentation is also included in the full download.&lt;br /&gt;&lt;br /&gt;Here is the full download of the &lt;a href="http://www.amillionpixels.us/CreateDynamics.zip"&gt;CreateDynamics &lt;/a&gt;toolkit.&lt;br /&gt;Here is the root &lt;a href="http://www.amillionpixels.us/readme.txt"&gt;readme.txt&lt;/a&gt;&lt;br /&gt;Here is the &lt;a href="http://www.amillionpixels.us/ChangeList.htm"&gt;change list documentation &lt;/a&gt;that lists all of the new stuff in the build.&lt;br /&gt;Here is the &lt;a href="http://www.amillionpixels.us/schema.xls"&gt;Excel spreadsheet&lt;/a&gt; that shows all of the serialized data items. This is used to auto-generate the source code for serialization now.&lt;br /&gt;The auto-generated &lt;a href="http://www.amillionpixels.us/NxuStream.chm"&gt;doxygen compatible documentation.&lt;/a&gt; (right click and do save as)&lt;br /&gt;Here is the previous &lt;a href="http://www.amillionpixels.us/NxuFaq.html"&gt;NxuStream FAQ&lt;/a&gt;.&lt;br /&gt;Here is the original &lt;a href="http://www.amillionpixels.us/toolkit.html"&gt;CreateDynamics documentation&lt;/a&gt;.&lt;br /&gt;The data layout as an &lt;a href="http://www.amillionpixels.us/schema.xsd"&gt;XML schema file &lt;/a&gt;(probably doesn't validate though, just for documentation).&lt;br /&gt;&lt;br /&gt;I have also been working to get the 3D Studio Max physics plugin and the Maya Nima plug-in updated to use this version of NxuStream. We have that working and it should be released fairly soon.&lt;br /&gt;&lt;br /&gt;I am also still trying to get my own 3d Studio Max plug-in to work but I am stuck because I can't get the objects to show up in the Max scene when I pass in my transforms. I have tried formulating my transform a bunch of different ways and have asked for some help but still no luck. It's very annoying that something so small like this can be a blocking factor. To get the rest of the 3D Studio Max create dynamics plug-in working would only take me a few hours if I could get it to accept my transforms.&lt;br /&gt;&lt;br /&gt;The source code to the plug-in is included with this drop. If you know max and can help me debug it I would appreciate it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-116069215905376073?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/CreateDynamics.zip' title='CreateDynamics and NxuStream update'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/116069215905376073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=116069215905376073' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116069215905376073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/116069215905376073'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2006/10/createdynamics-and-nxustream-update.html' title='CreateDynamics and NxuStream update'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-115955611363095780</id><published>2006-09-29T11:22:00.000-07:00</published><updated>2006-09-29T11:55:13.653-07:00</updated><title type='text'>Build instructions and Blog Comments</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/1252/124/1600/jessicaalbazink02jpg.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/1252/124/400/jessicaalbazink02jpg.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="font-size:85%;"&gt;(Photo caption: This photograph has absolutely nothing to do with the following post.  However, Jessica Alba sure is pretty to look at ain't she?)&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I just received a comment on my previous blog posting.  Thanks!  Now, send me a freaking email!  It is great to leave comments on blogs, especially if it is something you want to share with others.  However, you really need to send me a personal &lt;a href="mailto:jratcliff@infiniplex.net"&gt;email&lt;/a&gt;.   Blog comments are generally anonymous and I have no way to contact you other than making a fresh blog post.  And, as much as I enjoy posting new photographs of pretty girls, it is isn't the most efficient communication channel.&lt;br /&gt;&lt;br /&gt;Regarding the last blog comment where someone said they couldn't build the source.  You must change the #include paths to point to wherever your own install of the 3D Studio Max SDK is.  By default the project file points to my own personal install which is not going to be the same as yours.  Change the include path under C++ properties, the linker option, and the resource properties.&lt;br /&gt;&lt;br /&gt;This 3D Studio Max plug-in is definitely a work in progress.  I am just now learning about how to program the Max SDK and the learning curve is brutal.  I spent two hours yesterday just trying to set a freaking matrix transform and I still never got it to work right (even though I exported the data to disk and verified that my source transforms were fine, it's just a 'max thing').&lt;br /&gt;&lt;br /&gt;Recently I have been getting some bug reports that people are encountering crash problems with certain meshes or settings.  I am right now working on resolving these problems.  I am thrilled that people are finding the tool useful.  Originally I expected people just to use it for rocks, trees, tables, chairs, and that sort of thing (which it generally seems to do a good job with).  However, now I am finding out that people are trying to use it for entire level geometry!!&lt;br /&gt;&lt;br /&gt;It was not designed for that but now that I see people want to use it that way I will continue to work on it.&lt;br /&gt;&lt;br /&gt;The main reason the tool is limiting for such purposes is that it doesn't generate internal faces.  I am now working on a tool that generates solid geometry after a split.  This will prevent it from creating hollow interiors and conform much more accurately to the original mesh.&lt;br /&gt;&lt;br /&gt;I also am encountering problems when it attempts to recurse extremely deeply.  I will continue to post updates as I make progress.  That said, this is not my 'official project' and is mostly a hobby thing so I can only work on it as I make time available.&lt;br /&gt;&lt;br /&gt;Thanks, and please remember to email me directly with questions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-115955611363095780?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/fwmesh.zip' title='Build instructions and Blog Comments'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/115955611363095780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=115955611363095780' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/115955611363095780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/115955611363095780'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2006/09/build-instructions-and-blog-comments.html' title='Build instructions and Blog Comments'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-115852354452584899</id><published>2006-09-17T12:58:00.000-07:00</published><updated>2011-05-20T13:19:33.389-07:00</updated><title type='text'>Convex Decomposition 3d Studio Max 6 and above Plug-In (with source code)</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/1252/124/1600/DCP_2336.0.jpg"&gt;&lt;img alt="" border="0" src="http://photos1.blogger.com/blogger/1252/124/400/DCP_2336.0.jpg" style="cursor: hand;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;(Photo caption: My friend John Miles when he and I were taking a day trip in his Ferrari 308.)&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;***NOTICE ** NOTICE ** My convex decomposition library is now deprecated.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://codesuppository.blogspot.com/2011/05/hacd-hierarchical-approximate-convex.html"&gt;Please see this blog post for further details.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;I only had a little bit of time today to mess with my Convex Decomposition plug-in. This is my first 3d studio max plugin and I could not have written it without the help of my good friend Robert Sitton.&lt;br /&gt;&lt;br /&gt;I am hoping to spend a lot more time improving it in the coming weeks but I figured since this is at least functional I can release it and get feedback. I am also hoping some Max plug-in gurus might help me improve it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amillionpixels.us/meshfw.zip"&gt;Here is the link to the plug-in and source code.&lt;/a&gt; (137k download)&lt;br /&gt;&lt;br /&gt;Just copy the plug-in 'MESHFW.DLU' into your 3d Studio Max plug-ins folder.&lt;br /&gt;&lt;br /&gt;I have revised the source code to build against the Max 6 SDK.  That means this plug-in should work against all versions of Max 6 and higher.&lt;br /&gt;&lt;br /&gt;To use the plug-in just select an object you want to perform convex decomposition to. Go to the 'Utilities' page and select the plug-in called 'Mesh Framework'.&lt;br /&gt;&lt;br /&gt;You will be presented with a simple user interface that will let you control the recursion depth and thresholds.&lt;br /&gt;&lt;br /&gt;After clicking on the button to run it, it will perform the decomposition and insert the results of the approximate convex decomposition into the scene and delete the original mesh.&lt;br /&gt;&lt;br /&gt;If you don't like the results just hit Control-Z for an undo and try it again.&lt;br /&gt;&lt;br /&gt;Things the plug-in needs to do that I could use help on is:&lt;br /&gt;&lt;br /&gt;* The results of the convex decomposition should all be placed into a 'group' so that they can be manipulated as a single object.&lt;br /&gt;&lt;br /&gt;To build the source just load the solution file with .NET 2006.  You will *have* to change the include paths to whichever Max SDK version you have on your machine.&lt;br /&gt;&lt;br /&gt;I added some code that I thought was going to 'group' all of the objects together but it doesn't appear to be working.  Take a look at 'CreateDynamics.cpp' and search on the word 'group' in the source code.  If anyone has a bug fix for this it would be much appreciated.&lt;br /&gt;&lt;br /&gt;I, myself, will add the ability to produce approximations of boxes, spheres, and capsules, in addition to convex hulls.&lt;br /&gt;&lt;br /&gt;If you have time to take a look at this I welcome the feedback.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-115852354452584899?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/meshfw.zip' title='Convex Decomposition 3d Studio Max 6 and above Plug-In (with source code)'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/115852354452584899/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=115852354452584899' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/115852354452584899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/115852354452584899'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2006/09/convex-decomposition-3d-studio-max-6.html' title='Convex Decomposition 3d Studio Max 6 and above Plug-In (with source code)'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-115713597217393309</id><published>2006-09-01T11:20:00.000-07:00</published><updated>2006-09-01T12:46:49.873-07:00</updated><title type='text'>New release of CreateDynamics, PhysXViewer and NxuStream</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/1252/124/1600/HPIM0329.0.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/1252/124/400/HPIM0329.0.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Every time I make a post I like to include a photograph that somehow vaugley relates to the content. However, for this update, I just couldn't think of anything so I used a picture of my friends Simon and Christa from last summer.&lt;br /&gt;&lt;br /&gt;I just recently returned from GameFest. My talk with David Moore of Rad Game Tools went fine but there was a very small audience. It's hardly a surprise since we were scheduled against a presentation on the latest version of the HSL compiler; heck I wouldn't have gone to my own talk myself.&lt;br /&gt;&lt;br /&gt;Since I spent so much time on the content I will go ahead and make it available here as well.&lt;br /&gt;&lt;br /&gt;If you just want the slides only in a small download use this &lt;a href="http://www.amillionpixels.us/gamefest_slides.zip"&gt;link&lt;/a&gt;. (3mb)&lt;br /&gt;If you want the slides with the rather huge embedded movies, use t his &lt;a href="http://www.amillionpixels.us/gamefest.zip"&gt;link&lt;/a&gt;. (75mb)&lt;br /&gt;&lt;br /&gt;Most of my time has been spent finalizing the NxuStream data format. I have also been working on some documentation. Some of it you can access online and the rest is in the zip file itself.&lt;br /&gt;&lt;br /&gt;Here is a link to the &lt;a href="http://www.amillionpixels.us/nxustream/namespace_n_x_u.html"&gt;API documentation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here is a link to the &lt;a href="http://www.amillionpixels.us/NxuStreamSchema.xsd"&gt;NxuStream XML schema.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here is a link to the &lt;a href="http://www.amillionpixels.us/The%20NxuStream%20FAQ.htm"&gt;NxuStream FAQ&lt;/a&gt; that I am working on. If you have additional 'FAQ' questions please email them to me so I can revise the document.&lt;br /&gt;&lt;br /&gt;I am sorry that I have not made significant progress with the CreateDynamics toolkit itself or the new viewer application 'PhysXViewer'. I simply couldn't find time to work on these tools until the NxuStream data format was complete.&lt;br /&gt;&lt;br /&gt;My next little project is going to be to put the ConvexDecomposition library into a 3D Studio Max plug-in. As I become more comfortable programming in the Max SDK I hope to add more seamless support between CreateDynamics + PhysXViewer + NxuStream + COLLADA + 3D Studio Max.&lt;br /&gt;&lt;br /&gt;Finally, here is the link to the full &lt;a href="http://www.amillionpixels.us/CreateDynamics.zip"&gt;CreateDynamics.zip&lt;/a&gt; file. This contains the CreateDynamics toolkit, PhysXViewer, NxuStream, ConvexDecomposition, and a number of Samples and demos.&lt;br /&gt;&lt;br /&gt;This download is only 39MB. After you unzip it you can run 'CreateDynamics.bat' which will launch a custom version of Rocket that lets you play around with the toolkit. If you run 'PhysXViewer.bat' it will launch the PhysXViewer application (source provided). The PhysXViewer application doesn't have mouse dragging or other necessary features but, as I said, I hope to be getting back to that soon. Ultimately I will be transitioning away from the Rocket application and developing all of these tools within the context of the much smaller (and simpler) PhysXViewer framework.&lt;br /&gt;&lt;br /&gt;If you do not already have the PhysX 2.4.4 run-time installed on your machine then run the installer provided 'PhysX_2.4.4_FC4_SystemSoftware.exe'.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-115713597217393309?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/CreateDynamics.zip' title='New release of CreateDynamics, PhysXViewer and NxuStream'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/115713597217393309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=115713597217393309' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/115713597217393309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/115713597217393309'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2006/09/new-release-of-createdynamics.html' title='New release of CreateDynamics, PhysXViewer and NxuStream'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-115533464272161186</id><published>2006-08-11T14:56:00.000-07:00</published><updated>2006-09-01T11:20:34.910-07:00</updated><title type='text'>GameFest updated build</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/1252/124/1600/2005-Brink-Dynamics-Carver-Orange-SA-1024x768.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/1252/124/400/2005-Brink-Dynamics-Carver-Orange-SA-1024x768.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;&lt;strong&gt;I'm heading out of town to attend &lt;a href="http://www.microsoftgamefest.com/"&gt;GameFest &lt;/a&gt;and visit with my friends at &lt;a href="http://www.radgametools.com/"&gt;Rad GameTools&lt;/a&gt;.&lt;/strong&gt;&lt;/span&gt; My presentation at &lt;a href="http://www.microsoftgamefest.com/"&gt;GameFest &lt;/a&gt;is going to be about the CreateDynamics toolkit I am working on. I wanted to get a revised build put together before I left just so you could get the 'latest' version and I could get some feedback on it.&lt;br /&gt;&lt;br /&gt;Here is the link to a full version of the &lt;a href="http://www.amillionpixels.us/CreateDynamics.zip"&gt;CreateDynamics toolkit.&lt;/a&gt; In previous posts I uploaded individual components. I have not revised those links yet, so this download represents the 'current version' of the various sub-components in the system.&lt;br /&gt;&lt;br /&gt;The major changes to this build are:&lt;br /&gt;&lt;br /&gt;(1) Support of scene/model instancing in both NxuStream and &lt;a href="https://collada.org/public_forum/welcome.php"&gt;COLLADA&lt;/a&gt;.&lt;br /&gt;(2) A lot of improvements, bug fixes, and samples for the NxuStream code.&lt;br /&gt;(3) Pre-notification events for object creation.&lt;br /&gt;(4) The ability to construct a collection one object at a time.&lt;br /&gt;&lt;br /&gt;I won't get into the details of all of the changes I made but I have worked through many bugs over the past couple of weeks. I didn't make any significant changes to the actual create dynamics code, but I really look forward to getting back to that as soon as this file format stuff is fully put to bed.&lt;br /&gt;&lt;br /&gt;The major things I have left to work on are:&lt;br /&gt;&lt;br /&gt;(1) User property fields for all data objects.&lt;br /&gt;(2) Lots of documentation.&lt;br /&gt;&lt;br /&gt;Not all of these components require the PhysX 2.4.4 SDK to build. After you unzip the file, if you do not already have the PhysX 2.4.4 run-time component installed, you should run the provided system installer. This is *not* the SDK, just the run-time libraries.&lt;br /&gt;&lt;br /&gt;The following components build *without* the PhysX SDK:&lt;br /&gt;&lt;br /&gt;* &lt;strong&gt;CreateDynamics&lt;/strong&gt; [DLL plug-in to auto-generate physics from graphics data]&lt;br /&gt;* &lt;strong&gt;ConvexDecomposition&lt;/strong&gt; [Stand-alone convex decomposition library]&lt;br /&gt;* &lt;strong&gt;DAE2XML&lt;/strong&gt; [Demonstration application showing how to parse COLALDA 1.4.1 physics (needs to be revised with the support for physics models instancing physics models that is already in the NxuStream code]&lt;br /&gt;* &lt;strong&gt;DecomposeSample&lt;/strong&gt; [Console application demonstrating how to use ConvexDecomposition as a library]&lt;br /&gt;* &lt;strong&gt;PhysXRagdoll &lt;/strong&gt;[A console application demonstrating how to load and run the CreateDynamics tool as a plug-in DLL]&lt;br /&gt;&lt;br /&gt;The following components require the PhysX 2.4.4 SDK installed (to the default directories) to build. You may also need the DirectX SDK to build the PhysXViewer sample application. You can get the PhysX 2.4.4 SDK from the Ageia website.&lt;br /&gt;&lt;br /&gt;* &lt;strong&gt;LegacyNxuConvert&lt;/strong&gt; [Converts old legacy physx format (core dump) (ssa) to NxuStream]&lt;br /&gt;* &lt;strong&gt;NxuConvert&lt;/strong&gt; [Converts between XML, BINARY, and COLLADA forms of NxuStream data]&lt;br /&gt;* &lt;strong&gt;NxuStream&lt;/strong&gt; [The NxuStream library source code.]&lt;br /&gt;* &lt;strong&gt;PhysXViewer&lt;/strong&gt; [A prototpye application for viewing physics. Not very functional yet. Mostly provided to demonstrate the run-time binding to the Granny SDK. Much more work must be done on this application.]&lt;br /&gt;* &lt;strong&gt;Samples\SampleSceneExport&lt;/strong&gt; [An OpenGL sample application that shows how to import, export, and instantiate physics data and simulate it.]&lt;br /&gt;&lt;br /&gt;The following libraries will compile but with functionality disabled unless you are a Granny licensee:&lt;br /&gt;&lt;br /&gt;* &lt;strong&gt;Grimp&lt;/strong&gt; [Converts Granny data into a generic form for CreateDynamics to operate on]&lt;br /&gt;* &lt;strong&gt;GrannyPhysX&lt;/strong&gt; [The Granny to PhysX run-time binding layer]&lt;br /&gt;&lt;br /&gt;If you would like the latest drop of the NxuStream code just by itself you can use this &lt;a href="http://www.amillionpixels.us/NxuStream.zip"&gt;link&lt;/a&gt;. This includes an OpenGL sample application that shows how to import, export, and instantiate physics data using the NxuStream library.&lt;br /&gt;&lt;br /&gt;This is only a 2.5mb download and should compile out of the box with .NET 2003 and the PhysX 2.4.4 SDK installed on your machine (assuming you used the default directories).&lt;br /&gt;&lt;br /&gt;Right now the biggest problem with all of this stuff is lack of documentation. I will really get cranking on documentation when I return from GameFest a little over a week from now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-115533464272161186?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.amillionpixels.us/CreateDynamics.zip' title='GameFest updated build'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/115533464272161186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=115533464272161186' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/115533464272161186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/115533464272161186'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2006/08/gamefest-updated-build.html' title='GameFest updated build'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-115464195773688812</id><published>2006-08-03T14:33:00.000-07:00</published><updated>2006-08-07T11:15:37.583-07:00</updated><title type='text'>PhysX NxuStream file format</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/1252/124/1600/22444569.streamthroughthepine.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/1252/124/400/22444569.streamthroughthepine.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;How to get your physics data actually into a physics engine&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;While COLLADA 1.4.1 appears to a viable general purpose physics file format it may not be appropriate for a specific targeted physics SDK. The PhysX SDK uses the concept of 'descriptors' in its API to represent dynamics data. NxuStream is a pure reflective object model of these descriptors. What this means is that whatever the descriptor looks like in the API is exactly what it looks like in the XML file as well. The NxuStream library will load, save, and instantiate physics assets usng the PhysX SDK based on either COLLADA or NxuStream source. Additionally, the file can also be loaded and saved in binary format. The binary format can save out 'cooked' data which will load much faster than raw triangles.&lt;br /&gt;&lt;br /&gt;This version is probably in late alpha, early beta phase. It requires the PhysX 2.4.4 SDK to be installed on your machine. The PhysX 2.4.4 SDK is publically available at the Ageia website and I strongly recommend you check it out. If you don't use this physics SDK then this post is probably not very relevant to you.&lt;br /&gt;&lt;br /&gt;To my chagrin I have spent the past two weeks trying to seamlessly convert between COLLADA 1.4.1 physics and the native PhysX SDK format. It seems to me to be a ridiculous amount of time to spend on just parsing a stupid file format.&lt;br /&gt;&lt;br /&gt;Currently the NxuStream library is incorporated into your own software simply by adding the source to your project. It requires that you have include paths set to the PhysX SDK. Similar to compiling a Direct3D application.&lt;br /&gt;&lt;br /&gt;The source is wholey contained in a namspace 'NXU' and should not conflict with anything else in your application.&lt;br /&gt;&lt;br /&gt;To use it, all you have to do is include a single header file 'NXU_Helper.h'. A physics asset is referred to as an 'NxuPhysicsCollection'. This helper API lets you load a file in any of the 3 possible formats (NxuStream XML, NxuStream Binary, and COLLADA). You can then simply instantiate the asset relative to a root transform. There is also a 'save' method that will let you save it out in any of the three formats.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The deliverable contains&lt;/strong&gt;:&lt;br /&gt;&lt;br /&gt;NxuStream.xsd&lt;br /&gt;NxuStream.xsx : An XML 'schema' for NxuStream&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Directories&lt;/strong&gt;:&lt;br /&gt;&lt;br /&gt;NxuConvert : Contains a console application that converts from one format to another.&lt;br /&gt;NxuStream : Contains the NxuStream source code.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example usage:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;"NxuConvert beshon.xml beshon.dae" converts a file from NxuStream XML to COLLADA 1.4.1&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The NxuStream API in NXU_Helper.h is as follows&lt;/strong&gt;:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;loadCollection&lt;/strong&gt; : Loads a physics asset from disk.&lt;br /&gt;&lt;strong&gt;instantiateCollection&lt;/strong&gt; : Instantiates an asset relative to a root transform.&lt;br /&gt;&lt;strong&gt;releaseCollection&lt;/strong&gt; : Frees up the memory associated with the physics asset.&lt;br /&gt;&lt;strong&gt;coreDump&lt;/strong&gt; : A convenience function to save either the entire PhysX SDK or a single NxScene to a file on disk.&lt;br /&gt;&lt;strong&gt;extractCollectionSDK&lt;/strong&gt;: Copies the contents of the SDK to a collection.&lt;br /&gt;&lt;strong&gt;extractCollectionScene&lt;/strong&gt;: Copies the contents of a single NxScene to a colleciton.&lt;br /&gt;&lt;strong&gt;releasePersistentMemory&lt;/strong&gt;: Some persistent memory is allocated by the library to retain relationships between instantiated physics objects and their name to prevent multiple creations. It also needs a small amount of peristent memory for name fields. The application calls this routine on exit or when a reset of the SDK occurs.&lt;br /&gt;&lt;br /&gt;A user has the option of provided an error reporting interface so they can find out if and why anything failed. The application can also pass in an interface that notifies them *before* an object is created. This allows them to tweak the descriptor or decline to have the entity created. They are then notified when a physics object is successfully created so they can bind the userData field to their own internal game object.&lt;br /&gt;&lt;br /&gt;I have tried to keep the public interface simple. The implementation can be a bit overwhelming because the SDK can represent so much and so many types of data. Also, this code has gone through a lot of evolution and was touched by many programmers.&lt;br /&gt;&lt;br /&gt;Still to be done are transmission of custom user properties, asset instancing, the ability to load or save from an area in memory and just general cleanup.&lt;br /&gt;&lt;br /&gt;This code, already available on the PhysX website is provided here to show how one goes from COLLADA to a proprietary format or from a propietary format back to COLLADA. It also shows the full round-trip of not only loading assets but also instantiating them on a physics SDK.&lt;br /&gt;&lt;br /&gt;This flow of control system is integral to run-time binding of physics assets to game engines. For example, while working on the GrannyPhysX library, which binds the PhysX SDK to the Granny run-time engine, we used the NxuStream concept of a 'collection' to bind the individual bones in the graphics skeleton to specific rigid bodies and constraints in the physics engine.&lt;br /&gt;&lt;br /&gt;You can download this pre-release version of &lt;a href="http://aarm.mywowbb.com/~jratcliff/NxuStream.zip"&gt;NxuStream &lt;/a&gt;here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-115464195773688812?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://aarm.mywowbb.com/~jratcliff/NxuStream.zip' title='PhysX NxuStream file format'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/115464195773688812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=115464195773688812' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/115464195773688812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/115464195773688812'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2006/08/physx-nxustream-file-format.html' title='PhysX NxuStream file format'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-115463850134889871</id><published>2006-08-03T13:42:00.000-07:00</published><updated>2006-08-03T14:27:12.176-07:00</updated><title type='text'>PhysXViewer</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/1252/124/1600/0601_monatsthema_k.3.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/1252/124/400/0601_monatsthema_k.3.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;&lt;a href="http://aarm.mywowbb.com/~jratcliff/PhysXViewer.zip"&gt;The PhysXViewer&lt;/a&gt;&lt;/span&gt; allows you to use a graphics front end to experiment with the CreateDynamics toolkit. You can also import and export between COLLADA 1.4.1 physics and PhysX NxUStream. I am working on a new version of the PhysXViewer which is much more lightweight. This version is based on the Rocket application which, unfortunately, has grown quite large over the years. The new PhysXViewer will not be ready for release for probably another month or so. In the meantime you can run this custom version of Rocket.&lt;br /&gt;&lt;br /&gt;I fully expect that there are bugs with the COLLADA 1.4.1 physics imoprter and exporter. This is a pretty tricky format and it can be interpreted in a wide number of ways. However, I am working with other members of the COLLADA community to keep it in conformance. The goal, ultimately, is that you will be able to seamlessly interact with COLLADA physics data using Max, Maya, SoftImage, as well as the Feeling COLLADA viewer, Bullet Viewer, and the PhysXViewer.&lt;br /&gt;&lt;br /&gt;If you want to load either COLLADA physics data or NxuStream data directly into the PhysX SDK all you will need is the public 2.4.4 release of the SDK and the NxuStream library which is provided at the Ageia website.&lt;br /&gt;&lt;br /&gt;The PhysXViewer is about a 39mb download. Largely because it includes a great deal of sample data. If I removed all of the sample data and documentation it would be a very small download. However, it also woudln't be nearly as interesting either.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://aarm.mywowbb.com/~jratcliff/PhysXViewer.zip"&gt;You can downoad it from this link.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For a quick and easy demonstration of how to use it, follow these steps.&lt;br /&gt;&lt;br /&gt;After you unzip it you will need to install the PhysXSDK 2.4.4 core run-time libraries if you do not already have them installed on your machine.&lt;br /&gt;&lt;br /&gt;Run: PhysX_2.4.4_FC4_SystemSoftware.exe to install the run-time SDK components.&lt;br /&gt;&lt;br /&gt;Next, run the batch file 'PhysXViewer.bat'.&lt;br /&gt;&lt;br /&gt;Click on the button 'Dynamics Page'&lt;br /&gt;&lt;br /&gt;Under the combo 'graphics mesh' select 'character.bin'&lt;br /&gt;&lt;br /&gt;Then click the button 'create dynamics'.&lt;br /&gt;&lt;br /&gt;There is more documentation provided in the ZIP.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23430315-115463850134889871?l=codesuppository.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://aarm.mywowbb.com/~jratcliff/PhysXViewer.zip' title='PhysXViewer'/><link rel='replies' type='application/atom+xml' href='http://codesuppository.blogspot.com/feeds/115463850134889871/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=23430315&amp;postID=115463850134889871' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/115463850134889871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23430315/posts/default/115463850134889871'/><link rel='alternate' type='text/html' href='http://codesuppository.blogspot.com/2006/08/physxviewer.html' title='PhysXViewer'/><author><name>John</name><uri>http://www.blogger.com/profile/13580494289034594888</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_PtTKwwh_xBc/THaOvd2uZMI/AAAAAAAAHX8/Q0NtGZVDUIU/S220/john.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23430315.post-115463630034941204</id><published>2006-08-03T13:08:00.000-07:00</published><updated>2006-08-03T16:25:54.496-07:00</updated><title type='text'>The CreateDynamics Toolkit</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/1252/124/1600/AB22894_5.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/1252/124/400/AB22894_5.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Automatic Generation of Dynamics Data from Graphics Meshes, including Rag Doll models from Skeletal Deformed Meshes and Approximate Convex Decomposition.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The CreateDynamics toolkit is delivered both as source code and as a DLL plug-in. Unlike some of the previous offerings, there is a substantial amount of source code in this project. Could it be cleaned up? Yes, I'm sure it could. However, I have limited amounts of time and sometimes I have to take functionality over aesthetics.&lt;br /&gt;&lt;br /&gt;The key thing is you get source. That means you can rebuild it. The second key thing is you get a plug-in, so you can use this as a 'tool' without having to worry about the source at all.&lt;br /&gt;&lt;br /&gt;After this shaky introduction I suppose you are wondering what the heck does it do?&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;What is the CreateDynamics Toolkit?&lt;/strong&gt; CreateDynamics is an open source library that automatically generates dynamics data from static or deformed skeletal meshes. It can be used as a DLL plug-in or the source can be linked directly into your own application.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;What formats does it accept?&lt;/strong&gt; For deformed skeletal meshes CreateDynamics can read the Unreal PSK file format or Granny 2 files generated from the Rad Game Tools exporter. You must be a licensee of Granny to have access to the exporter and sources.&lt;br /&gt;&lt;br /&gt;For static mesh data it accepts Unreal PSK, Granny 2, and Wavefront OBJ files. You can also submit your own raw static data directly through the API. There is not yet a public interface to submit raw skeletal deformed meshes. However, if this is a feature people would like to have it can be added. (You must be a Granny licensee to build the source with Granny support.)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;What kind of dynamics data does it generate?&lt;/strong&gt; CreateDynamics can interpret a deformed skeletal mesh and infer a constrained ‘rag doll’ model from it. It can convert the input geometry into a format suitable for cloth simulation. Finally, it can perform approximate convex decomposition to produce efficient collision models for mesh data. Collision fitting supports convex hulls, boxes, spheres, and capsules.&lt;br /&gt;&lt;br /&gt;Future versions will provide improved support for constrained systems and cloth modeling.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;What data formats does it produce?&lt;/strong&gt; CreateDynamics generates output data in PSCL, COLLADA and NxUstream formats. PSCL stands for the ‘physics scripting language’ which is used by the PhysX Rocket application. It is easily human readable and generally useful for debugging. No source code library is provided to read PSCL for a game engine. If there is a strong need for such a tool it might be made available.&lt;br /&gt;&lt;br /&gt;The format promoted by Ageia is ‘NxUStream’ which is a reflective object model of the PhysX SDK stored in either XML or binary form. A complete XML schema is provided. The CreateDynamics toolkit exports data in XML form and can then be converted into binary for your target platform by running the tool NxuConvert. The file name extension adopted for PSCL is ‘.PSC’. NxUStream uses ‘.XML’ for XML and ‘.NXB’ for the binary version. COLLADA files have the extension of ‘.DAE’.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Can I generate my own file format?&lt;/strong&gt; Yes. There is a single source file in the CreateDynamics library which writes the output data to disk. It is a relatively simple and straightforward task to modify this source to save the data out in any format you see fit. The source file is called ‘Accumulate.cpp’ and is located in ‘\CreateDynamics\AutoPhysX’.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Does CreateDynamics output COLLADA physics?&lt;/strong&gt; The CreateDynamics toolkit now has basic support for COLLADA physics import and export. Use the import and export options under the file menu to load and save a COLLADA .dae file. This can be imported in other tools using COLLADA-DOM, FCollada or your custom parser. COLLADA physics content can be created using various tools like Maya, Max, XSI and Blender 2.42.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;What features will future versions of CreateDynamics support?&lt;/strong&gt; Future versions of the CreateDynamics toolkit might provide support for pre-fractured assets and automatic generation of deformed skeletal meshes for soft-body simulations. Since each of these features must operate on both the graphics data as well as the physics data they present significant architectural design challenges&lt;br /&gt;&lt;br /&gt;While it is relatively simple to produce a ‘fractured object’ representation by taking advantage of the aggregate convex decomposition library, it is much more difficult to produce the graphics representation of the object at the appropriate split boundaries. Automatically generating a deformed skeletal mesh is a more straightforward project; but selecting a format for the graphics representation is an open question.&lt;br /&gt;&lt;br /&gt;Better support for cloth conversion as well as improved user interfaces and API would be likely feature improvements as well.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Does CreateDynamics work with 3D Studio Max or Maya?&lt;/strong&gt; Not currently. While it is certainly a long term goal to integrate the features of CreateDynamics into these production tools it is not ready for that yet. We feel it is better to make a version of the tool available to developers for early feedback and give them the opportunity to integrate it into their own tools pipeline. By providing it in open source form, as well as a DLL plug-in, we hope to engage the development community in the evolution of this project.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;How can I use CreateDynamics as a stand-alone production tool?&lt;/strong&gt; CreateDynamics has been integrated into a stripped down version of PhysX Rocket. It provides a graphics front end that allows you to easily experiment with the features of the tool. CreateDynamics can also be used as a console application from the command line. One of the most exciting opportunities provided by the CreateDynamics library is the ability to batch convert a large number of game assets based on a set of scripted rules.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;How do I convert my own assets with PhysX Viewer?&lt;/strong&gt; Simply drop a PSK, GR2, or Wavefront OBJ file into the directory ‘\PhysXViewer\data\mesh’ and it will show up in the menus.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Where do I find my output?&lt;/strong&gt; After converting an input graphics mesh into a dynamics asset the DLL will produce two output files; one in PSCL and one in XML. Rocket runs the PSCL version by default since it can bind with the source graphics. To run the NxUstream file directly select the checkbox ‘use nxustream’. If you do this you will only see the dynamics assets.&lt;br /&gt;&lt;br /&gt;If you were to convert a file called ‘test.obj’ you would get as outputs&lt;br /&gt;&lt;br /&gt;‘\CreateDynamics\data\pscl\test.psc’&lt;br /&gt;‘\CreateDynamics\data\pscl\test.xml’&lt;br /&gt;‘\CreateDynamics\data\pscl\test.dae'&lt;br /&gt;&lt;br /&gt;&lt;str
