<?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-17188375</id><updated>2012-01-30T09:11:26.787+08:00</updated><category term='magic2010'/><category term='education'/><category term='demoscene'/><category term='GPGPU'/><category term='AI'/><category term='robotics'/><category term='os'/><category term='compilers'/><category term='programming'/><category term='raytracing'/><category term='mining'/><category term='fluid'/><category term='graphics'/><category term='games'/><category term='project management'/><category term='physics'/><category term='COLLADA'/><category term='PAL'/><category term='computers'/><title type='text'>Adrian Boeing: Blog</title><subtitle type='html'>Also check out &lt;a href="http://www.adrianboeing.com"&gt;Adrian Boeing's webpage&lt;/a&gt;.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default?start-index=101&amp;max-results=100'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>241</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-17188375.post-7563548398435064100</id><published>2012-01-12T22:22:00.000+08:00</published><updated>2012-01-12T22:22:24.559+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><title type='text'>Kinect viewer with HTML5 canvas</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I wanted to create a web-based Kinect viewer that would work on multiple platforms, including Android mobile phones and iPhones. To this end, I created a HTML5 canvas particle viewer for Kinect data using my very limited javascript knowledge and a lot of &lt;a href="http://mrdoob.com/"&gt;Mr. doob's&lt;/a&gt; knowledge. &lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-klvP8ew25kM/Tw7sIdBI50I/AAAAAAAAAds/iGo8SFiQLAY/s1600/kinectparticles.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="165" src="http://2.bp.blogspot.com/-klvP8ew25kM/Tw7sIdBI50I/AAAAAAAAAds/iGo8SFiQLAY/s200/kinectparticles.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Kinect HTML5 particle image&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Take a look at the &lt;a href="http://www.adrianboeing.com/demoscene/test/particleimage/canvas_particles_image.html"&gt;HTML5 Kinect particle image viewer&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Using libfreenect I captured the depth and color data, used Imagemagik and an Automator script to process and stich the images, and &lt;a href="http://threejs.org/"&gt;threejs&lt;/a&gt; to render.&lt;br /&gt;&lt;br /&gt;You can extract data from an image by rendering it to a hidden canvas element, and then reading the canvas image data. To avoid errors, the image data should only be read after the full image has been loaded, as per the callback function in loadTexture.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;function getImageData( image ) {&lt;br /&gt;var canvas = document.createElement( 'canvas' );&lt;br /&gt;canvas.width = image.width;&lt;br /&gt;canvas.height = image.height;&lt;br /&gt;var context = canvas.getContext( '2d' );&lt;br /&gt;context.drawImage( image, 0, 0 );&lt;br /&gt;return context.getImageData( 0, 0, image.width, image.height );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function getPixel( imagedata, x, y ) {&lt;br /&gt;var position = ( x + imagedata.width * y ) * 4, data = imagedata.data;&lt;br /&gt;return { r: data[ position ], g: data[ position + 1 ], b: data[ position + 2 ], a: data[ position + 3 ] };&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var texture, imagedata;&lt;br /&gt;texture = THREE.ImageUtils.loadTexture( "textures/sprites/spark1.png", new THREE.UVMapping(), function ( event ) {&lt;br /&gt;imagedata = getImageData( texture.image );&lt;br /&gt;} );&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;To run the system locally, avoiding some of Chromes very annoying security settings, you can just use python to run a simple webserver:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;python -m SimpleHTTPServer&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I recorded a short data sequence and rendered to sprites to create this final 3d home move with the Kinect (too slow for my phone to render). I believe this is the first web-based kinect video ever made, youtube3d anyone?&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://www.adrianboeing.com/demoscene/test/particleimage/canvas_particles_kinect_sprite_anim.html" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="239" src="http://4.bp.blogspot.com/-s-3I0MpsX8c/Tw7sWzWSHSI/AAAAAAAAAd0/1pOukB7nfmM/s320/kinectsprite.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.adrianboeing.com/demoscene/test/particleimage/canvas_particles_kinect_sprite_anim.html"&gt;Animated 3D kinect data with HTML sprites&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Next time, I might try WebGL...&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-7563548398435064100?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/7563548398435064100/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=7563548398435064100' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7563548398435064100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7563548398435064100'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2012/01/kinect-viewer-with-html5-canvas.html' title='Kinect viewer with HTML5 canvas'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-klvP8ew25kM/Tw7sIdBI50I/AAAAAAAAAds/iGo8SFiQLAY/s72-c/kinectparticles.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-9210799339143958178</id><published>2012-01-11T21:25:00.000+08:00</published><updated>2012-01-11T21:25:24.634+08:00</updated><title type='text'>2011 Wrapup</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-dZPE8d7SaRs/Tw2NtmGNLdI/AAAAAAAAAdE/1oSLiC72lB0/s1600/Fire-Works-Happy-New-Year-2012-small.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="150" src="http://1.bp.blogspot.com/-dZPE8d7SaRs/Tw2NtmGNLdI/AAAAAAAAAdE/1oSLiC72lB0/s200/Fire-Works-Happy-New-Year-2012-small.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;Looking back, 2011 was certainly a quieter year than 2010. Personal life got busy in the later half of the year, so less was posted. My job also took a less technical turn as I moved away from software development.&lt;br /&gt;By far my most popular posts concerned my analysis of some popular demo scene effects and WebGL:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The most popular posts were on &lt;a href="http://adrianboeing.blogspot.com/2011/02/ripple-effect-in-webgl.html"&gt;Ripple effect&lt;/a&gt;, &lt;a href="http://adrianboeing.blogspot.com/2011/01/raycasting-two-planes-in-webgl.html"&gt;Raycasting planes&lt;/a&gt;, &lt;a href="http://adrianboeing.blogspot.com/2011/01/twist-effect-in-webgl.html"&gt;Twist effect&lt;/a&gt;, &lt;a href="http://adrianboeing.blogspot.com/search?q=effect"&gt;many more demoscene effects explained&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://pouet.net/prod.php?which=57739"&gt;The self-explanatory demo&lt;/a&gt;, was well received, scratching into the top of the month for pouet for a while, and coming 3rd at the Mozzila demoparty. This animates the explanation behind a number of the demo effects.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://adrianboeing.blogspot.com/2011/05/slides-on-demoscene-and-webgl-demo.html"&gt;Slides&lt;/a&gt; on a guest lecture that cover some of the details of these effects again.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Otherwise, a survey / summary post on &lt;a href="http://adrianboeing.blogspot.com/2011/01/executable-compression.html"&gt;exe compression for multiple platforms&lt;/a&gt; was well read, and my &lt;a href="http://adrianboeing.blogspot.com/2011/09/civilization-5-casualfast-game-mod-for.html"&gt;Civ 5 casual game mod&lt;/a&gt; proved popular too.&lt;br /&gt;&lt;br /&gt;I will try to post a bit more about work and the mining industry, not because these are popular posts, but because there is so little information about this field on the web. I hope to post more about robotics and graphics (raytracing), and will try to open source and post about some of my past work.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-9210799339143958178?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/9210799339143958178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=9210799339143958178' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/9210799339143958178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/9210799339143958178'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2012/01/2011-wrapup.html' title='2011 Wrapup'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-dZPE8d7SaRs/Tw2NtmGNLdI/AAAAAAAAAdE/1oSLiC72lB0/s72-c/Fire-Works-Happy-New-Year-2012-small.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-6373708521030293793</id><published>2011-12-12T22:11:00.000+08:00</published><updated>2011-12-12T22:11:39.796+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='raytracing'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='GPGPU'/><title type='text'>GPU and Graphics catchup post</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;It has been a long while since I've done a graphics related post, so here is a bit of a backlog from the last few months of graphics and GPU links:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://github.com/TTimo/doom3.gpl"&gt;Doom 3 source code&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://kevinkarsch.com/publications/sa11.html"&gt;Kevin Karsh's work on rendering objects into photos&lt;/a&gt; is definitely worth a look if you haven't already seen it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.webupd8.org/2011/09/gtk-32-released-with-html5-allows.html"&gt;GTK now supports a HTML5 target&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://imgtec.com/powervr/insider/powervr-sdk-docs.asp"&gt;PowerVR&lt;/a&gt; have a great collection of articles, a nice resource to add alongside nVidia and AMD's developer zones.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.khronos.org/news/press/khronos-releases-opencl-1.2-specification"&gt;OpenCL 1.2&lt;/a&gt; was released.&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/sfera/"&gt;Sfera&lt;/a&gt; an open source OpenCL realtime pathtracing game&lt;/li&gt;&lt;li&gt;A great &lt;a href="http://www.youtube.com/watch_popup?v=XVTga6GmbGw&amp;amp;vq=medium#t=74"&gt;projection onto a building facade in Berlin&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.streamcomputing.eu/blog/2011-09-28/the-current-state-of-webcl/"&gt;WebCL&lt;/a&gt; has been making good progress. &lt;a href="http://www.geeks3d.com/20110822/webcl-nokia-extension-for-firefox-6-and-kernel-toy/?utm_source=feedburner&amp;amp;utm_medium=feed&amp;amp;utm_campaign=Feed%3A+TheGeeksOf3d+%28The+Geeks+Of+3D%29"&gt;Nokia released a WebCL plugin&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Epic Games posted a nice long &lt;a href="http://www.youtube.com/watch?v=C08yJ8_R3j4"&gt;video of the work involved in creating content for Gears of War&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Fixstars released a short &lt;a href="http://www.fixstars.com/en/opencl/book/OpenCLProgrammingBook/contents.html"&gt;OpenCL programming book&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.cs.cmu.edu/afs/cs/academic/class/15869-f11/www/"&gt;Content for CMU Graphics and Imaging Architectures&lt;/a&gt; have been released.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thejit.org/"&gt;Javascript info toolkit&lt;/a&gt; makes awesome visualizations of charts, graphs, and trees.&lt;/li&gt;&lt;li&gt;Progress is being made to run &lt;a href="http://www.eetimes.com/electronics-news/4230602/OpenCL-gets-upgrade--Altera-tips-FPGA-tool?pageNumber=1"&gt;OpenCL on a FPGA by Altera&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.xnormal.net/1.aspx"&gt;Xnormal&lt;/a&gt; creates normal maps, and now supports OpenRL.&lt;/li&gt;&lt;li&gt;A nice &lt;a href="http://lodev.org/cgtutor/randomnoise.html"&gt;tutorial on generating texture maps with noise&lt;/a&gt; using shaders.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.disneyanimation.com/technology/opensource.html"&gt;Disney's open source&lt;/a&gt; collection has been updated - uv-less texture mapping, scripting/server tools, particle file formats, and the Dynamica Maya plug-in for the Bullet physics engine.&lt;/li&gt;&lt;li&gt;&lt;a href="http://gpgpu.org/2011/12/07/intel-spmd-compiler-version-1-1-released"&gt;Intel SPMD v1.1&lt;/a&gt; parallel compiler was released.&lt;/li&gt;&lt;li&gt;Intel's &lt;a href="http://software.intel.com/en-us/articles/opencl-sdk/"&gt;OpenCL SDK&lt;/a&gt; has seen a number of updates.&lt;/li&gt;&lt;li&gt;&lt;a href="http://software.intel.com/en-us/articles/intel-cilk-plus/"&gt;Intel Cilk&lt;/a&gt; is a new parallel extension for C++.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/cudpp/"&gt;Cuda performance primitives&lt;/a&gt; has reached release 2.0&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.streamcomputing.eu/blog/2011-08-03/aparapi-is-opencl-in-java/"&gt;Adarapi&lt;/a&gt; lets you write OpenCL with Java.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A nice &lt;a href="http://matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp"&gt;description of the GIF file format&lt;/a&gt;&lt;/li&gt;&lt;li&gt;A new release of &lt;a href="http://www.ctrl-alt-test.fr/?p=358"&gt;ShaderMinifier&lt;/a&gt; to help reduce your shader file size.&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/glintercept/"&gt;GL intercept&lt;/a&gt; is a nifty tool that logs all your applications OpenGL calls. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://parse.ele.tue.nl/publications?tag=GPU"&gt;PARSE research group&lt;/a&gt; have a number of interesting GPU image processing projects, including Hough Transforms and Speed Sign Detection.  &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://tideart.com/"&gt;TideArt&lt;/a&gt; has interesting graphics related articles and tutorials.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;Finally, I'll leave you with a fantastic &lt;a href="http://pouet.net/prod.php?which=57449"&gt;64kb demo by Fairlight and Alcatraz&lt;/a&gt; that placed 2nd at Assembly 2011. &lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/69Xjc7eklxE" width="560"&gt;&lt;/iframe&gt;  &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-6373708521030293793?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/6373708521030293793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=6373708521030293793' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6373708521030293793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6373708521030293793'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/12/gpu-and-graphics-catchup-post.html' title='GPU and Graphics catchup post'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/69Xjc7eklxE/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-860429514997092215</id><published>2011-11-29T22:14:00.002+08:00</published><updated>2012-01-12T21:52:03.334+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mining'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><title type='text'>Remotely Operated Mining</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-9tZ6f2hXsHM/TtTop16cstI/AAAAAAAAAc4/iZFjYAAuAps/s1600/image_mini.jpeg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-9tZ6f2hXsHM/TtTop16cstI/AAAAAAAAAc4/iZFjYAAuAps/s1600/image_mini.jpeg" /&gt;&lt;/a&gt;&lt;/div&gt;I gave a presentation on the &lt;a href="http://www.transmin.com.au/"&gt;Transmin&lt;/a&gt; &lt;a href="http://www.rocklogic.com.au/"&gt;Rocklogic rock breaker automation system&lt;/a&gt; at the &lt;a href="http://www.informa.com.au/conferences/mining/operations/remotely-operated-mining-projects"&gt;Remotely Operated Mining Projects&lt;/a&gt; conference. All in all it was a fairly decent conference focused around the theme of remote operations for mining, focusing predominantly on integrated planning, remote operation technology, and the design and construction of remote operation centers.&lt;br /&gt;&lt;br /&gt;Talks were given by:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Greg Lilleyman, Rio Tinto - an overview of remote operations&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Matthew Michalewicz, SolveIT - integrated planning for mature organizations, interesting overview of some of the wine industry supply chain issues&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Patrick Warrand, Wesfarmers Premier Coal - a open overview of issues for 'small' mining operations (Note: Small is of course a relative term compared to the massive operations of BHP and Rio)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Jeremy Newman, Schneider Electric - a suppliers point of view to automation&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Jock Cunningham, CSIRO - an overview of CSIRO activity in mining, and their SLAM technology. (&lt;a href="http://www.wambot.org/"&gt;WAMBOT&lt;/a&gt; was multi-agent SLAM, CSIRO does automotive SLAM and a novel handheld indoor SLAM 'Zebedee')&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Brendon, Leica Geosystems - an overview of &lt;a href="http://www.autonomoussolutions.com/"&gt;Autonomous Solutions Inc&lt;/a&gt; (they do lots of autonomous systems for military and agriculture), and &lt;a href="http://www.locatacorp.com/"&gt;Locata&lt;/a&gt; - a GPS alternative&lt;br /&gt;&lt;/li&gt;&lt;li&gt;David Beck, &lt;a href="http://www.beckengineering.com.au/"&gt;Beck Engineering&lt;/a&gt; - a case study of Simulation Aided Engineering&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.adrianboeing.com/"&gt;Adrian Boeing&lt;/a&gt;, &lt;a href="http://www.transmin.com.au/"&gt;Transmin&lt;/a&gt; - remotely operated rockbreaking&lt;br /&gt;&lt;/li&gt;&lt;li&gt;David Cavanagh, Integrated Energy - an overview of remote operation center designs for oil and gas, and mining&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Lucas van Latum, Modular Mining - Goal orientated planning and the &lt;a href="http://en.wikipedia.org/wiki/OODA_loop"&gt;Observe-Orientate-Decide-Act&lt;/a&gt; loop&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Reuben Kooperman and Peter Hunt - architecture for Remote Operation Centers (or Integrated Planning Centers) - including two buildings I go past on a regular basis and never fully realised what goes on inside - the City of Stirling building, and the ECU Joondalup library.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Mike Lomman, &lt;a href="http://www.opxsolutions.com/"&gt;OpX Solutions&lt;/a&gt; - planning considering bottlenecks&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Andrew Jessett, &lt;a href="http://www.mineware.com.au/"&gt;MineWare&lt;/a&gt; - realtime dragline and shovel monitoring and support/maintenance orientated ROC's.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;David Hattrick, Oracle Corporation - Oracles approach to managing mining data and information&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Richard Taylor, Concept AV - Video walls&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;I put the Rocklogic animation up on youtube, it's pretty neat. Gives a short overview of the systems features - Remote operation, collision avoidance, automated movements (auto-park, auto-deploy), etc. &lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/JOQL9wfvHyc" width="560"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-860429514997092215?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/860429514997092215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=860429514997092215' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/860429514997092215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/860429514997092215'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/11/remotely-operated-mining.html' title='Remotely Operated Mining'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-9tZ6f2hXsHM/TtTop16cstI/AAAAAAAAAc4/iZFjYAAuAps/s72-c/image_mini.jpeg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-1145486120360941584</id><published>2011-11-23T21:24:00.002+08:00</published><updated>2011-11-29T21:30:12.024+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='computers'/><title type='text'>PDF tools</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-SNkhs26Xn-Y/TtTeQWGbkGI/AAAAAAAAAcw/qZbLllb6BxQ/s1600/pdf-file-logo-icon.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/-SNkhs26Xn-Y/TtTeQWGbkGI/AAAAAAAAAcw/qZbLllb6BxQ/s200/pdf-file-logo-icon.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;PDF files are the standard document distribution format. PDF has long left other file formats in the dust. However, there are always a number of operations that people like to make to PDF's ranging from just creating them, to splitting or merging to applying a watermark or foreground stamp.&lt;br /&gt;&lt;br /&gt;There are a number of great free tools to do all this work.&lt;br /&gt;&lt;br /&gt;&lt;li&gt; &lt;a href="http://sourceforge.net/projects/pdfcreator/"&gt;PDF Creator&lt;/a&gt; lets you create PDF files in Windows. Another popular alternative is &lt;a href="http://www.cutepdf.com/"&gt;CutePDF&lt;/a&gt;. For Apple Mac, under OSX you can simply print straight to PDF.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Splitting/bursting and merging/combining PDFs I feel is best done with a dedicated tool, &lt;a href="http://www.pdfsam.org/"&gt;PDFSAM - Split and Merge&lt;/a&gt;. Under OSX, you can actually use the sidebar of preview to move pages around, and drag in PDFs to merge, or pages to remove. If you have a lot of pages to do PDFSAM is a wiser choice, otherwise for smaller tasks Preview is fine.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Compression of PDFs under OSX is also straight forward, you just need to open the PDF in preview, and then under Quartz filter choose "Reduce File Size". Under windows, you can use PDFTK, more on this later.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Annotation of PDFs, again with OSX, preview gives you a small set of annotation tools. Under windows, you can use PDFTK. (Low cost / free for some-things aternatives are &lt;a href="http://www.tracker-software.com/product/pdf-xchange-viewer"&gt;PDF-Xchange viewer&lt;/a&gt; and &lt;a href="http://www.foxitsoftware.com/Secure_PDF_Reader/"&gt;Foxit Reader&lt;/a&gt;)&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Watermarking and Stamps are best done with PDFTK.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Encryption can be done with PDFTK, and under OSX, preview has an encrypt option.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Of course for those with cash, Adobe's tools are the best choice, but &lt;a href="http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/"&gt;pdftk&lt;/a&gt; is a fantastic free alternative, if you don't mind a bit of command line typing.&lt;br /&gt;&lt;br /&gt;An example of putting a foreground stamp onto every PDF with pdftk:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Generate a PDF where you would like to apply the stamp to (i.e. the source)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Create a stamp PDF. This should have the stamp you wish to apply (e.g. "DRAFT") and be a transparent PDF. Microsoft Word will generate transparent PDFs by default, so you can create your stamp in Word.&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Apply the stamp to the source PDF using pdftk, for example:&lt;br /&gt;&lt;pre&gt;pdftk in.pdf stamp stamp.pdf output out.pdf&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Enjoy!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-1145486120360941584?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/1145486120360941584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=1145486120360941584' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/1145486120360941584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/1145486120360941584'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/11/pdf-tools.html' title='PDF tools'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-SNkhs26Xn-Y/TtTeQWGbkGI/AAAAAAAAAcw/qZbLllb6BxQ/s72-c/pdf-file-logo-icon.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-4181846860755581231</id><published>2011-09-25T13:02:00.000+08:00</published><updated>2011-09-25T13:02:22.995+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><title type='text'>Robotics competitions and courses</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-nDtqNGacxwQ/Tn61u7TRKfI/AAAAAAAAAcY/1XZY02z-3Qs/s1600/samplechallengeoriginal.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/-nDtqNGacxwQ/Tn61u7TRKfI/AAAAAAAAAcY/1XZY02z-3Qs/s320/samplechallengeoriginal.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Sounds like it is competition season again.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.uavoutbackchallenge.com.au/2011/"&gt;UAV outback challenge&lt;/a&gt; where an unmanned ariel vehicle needs to find a person and drop supplies off to them. Registrations are due on the 27th September!&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.nasa.gov/offices/oct/early_stage_innovation/centennial_challenges/sample_return_robot/index.html"&gt;NASA Sample Return Centennial Challenge&lt;/a&gt;, a 1.5 million dollar prize competition to have robots autonomously explore a region, collect samples, and bring them back to base. Registration due in January, with the competition set for June. Only 8 months before the deadline when they announced the competition details - what are they thinking? &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://solutionsinperception.org/overView.html"&gt;The ICRA solutions in perception challenge&lt;/a&gt; (May 2012), this doesn't seem too difficult - Identify and classify a set of objects, where you are given some training data/time. Use any sensor(s) you like.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Australian &lt;a href="http://www.cisra.com.au/extremeimaging.html"&gt;CiSRA ExtremeImaging competition&lt;/a&gt; an interesting computer-photography competition, due October this year, finals in November.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Many more are listed &lt;a href="http://robots.net/rcfaq.html"&gt;at the robot contests and competitions FAQ&lt;/a&gt;.  To get you up to speed with robotics, there are some great free courses being run. The stanford &lt;a href="http://ml-class.org/"&gt;Machine Learning course&lt;/a&gt; and the &lt;a href="http://www.ai-class.com/"&gt;Introduction to AI class&lt;/a&gt; are both free to register, and start now! The ESA &lt;a href="http://sophia.estec.esa.int/socis2011/"&gt;summer of code in space&lt;/a&gt; already started last month, but it is worth keeping an eye on for next time.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-4181846860755581231?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/4181846860755581231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=4181846860755581231' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/4181846860755581231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/4181846860755581231'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/09/robotics-competitions-and-courses.html' title='Robotics competitions and courses'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-nDtqNGacxwQ/Tn61u7TRKfI/AAAAAAAAAcY/1XZY02z-3Qs/s72-c/samplechallengeoriginal.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-5511905784543875974</id><published>2011-09-12T22:17:00.000+08:00</published><updated>2011-09-12T22:17:13.467+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><title type='text'>Civilization 5 - Casual/fast game mod for Apple Mac OSX</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-d_kr2XhkMNs/Tm4UQBJ56VI/AAAAAAAAAcU/Sxhe8kBxyxQ/s1600/civ5-small.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="209" src="http://3.bp.blogspot.com/-d_kr2XhkMNs/Tm4UQBJ56VI/AAAAAAAAAcU/Sxhe8kBxyxQ/s320/civ5-small.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;I rarely have enough spare time these days to be able to play a game, let alone identify a block of time large enough to dedicate to a game like Civilization 5 - which can take up to 12 hours to play a fast game. So I decided to create a mod for Civ 5 that would significantly speed up gameplay and enable a game to be completed in a few hours.&lt;br /&gt;&lt;br /&gt;Modding the game isn't directly supported under OSX, however it can be done.&lt;br /&gt;&lt;br /&gt;First, edit MainMenu.lua, located in:&lt;br /&gt;&lt;pre&gt;~/Library/Application Support/Steam/SteamApps/common/sid meier's civilization v/Assets/UI/FrontEnd&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Comment the following line: (add a '--' to the start)&lt;br /&gt;&lt;pre&gt;Controls.ModsButton:SetHide( true );&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Copy a mod you have downloaded into the:&lt;br /&gt;&lt;pre&gt;~/Documents/Aspyr/Sid Meier's Civilization 5/MODS&lt;br /&gt;&lt;/pre&gt;directory.&lt;br /&gt;&lt;br /&gt;You will need to unzip/extract them before they will work.&lt;br /&gt;If it is a civ5mod file, simply rename it to .7z, and you can use StuffitExpander or any similar tool to extract the folder.&lt;br /&gt;&lt;br /&gt;Start Civ5, and you should see a 'MOD' option on the menu.&lt;br /&gt;&lt;br /&gt;Creating your own mods is easy enough if you know how. Armed with a decent text editor and the console you can create mods under OSX. Begin by reading &lt;a href="http://www.weplayciv.com/forums/entry.php?22-The-way-to-a-man-s-heart-is-through-his-modinfo-and-civ5mod-files.&amp;amp;"&gt;Dale's explanation of modinfo files&lt;/a&gt;. Next, the &lt;a href="http://wiki.2kgames.com/civ5/index.php/Main_Page"&gt;2K games Civilization 5 wiki&lt;/a&gt; is a good place to visit, in particular the &lt;a href="http://wiki.2kgames.com/civ5/index.php/XML_Reference"&gt;Civ 5 XML reference guide&lt;/a&gt;. Finally, the &lt;a href="http://kael.civfanatics.net/files/ModdersGuide.pdf"&gt;civfanatics modders guide&lt;/a&gt; provides an excellent overview of creating a mod.&lt;br /&gt;&lt;br /&gt;You can use the command line 'md5' program to generate the MD5 hashes required for the modinfo file. (And &lt;a href="http://www.string-functions.com/case.aspx"&gt;online lower-to-uppercase conversion&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;You can download my simple &lt;a href="http://www.adrianboeing.com/files/Casual%20Mod.zip"&gt;casual gaming mod for Civilization 5 here&lt;/a&gt;. It replaces the standard 'quick' game. At the beginning of the game, you will find most things only take one turn to complete. Things will start to settle down quickly though in classical times.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-5511905784543875974?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/5511905784543875974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=5511905784543875974' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5511905784543875974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5511905784543875974'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/09/civilization-5-casualfast-game-mod-for.html' title='Civilization 5 - Casual/fast game mod for Apple Mac OSX'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-d_kr2XhkMNs/Tm4UQBJ56VI/AAAAAAAAAcU/Sxhe8kBxyxQ/s72-c/civ5-small.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-1022910559989587659</id><published>2011-09-06T21:51:00.015+08:00</published><updated>2012-01-11T21:58:34.751+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='magic2010'/><title type='text'>Eureka Prize for WAMbot</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-xWI6NnYnZZA/Tw2Vd796HMI/AAAAAAAAAdM/CDrH4okMzNc/s1600/1103_WAMbot.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-xWI6NnYnZZA/Tw2Vd796HMI/AAAAAAAAAdM/CDrH4okMzNc/s1600/1103_WAMbot.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;The Australian &lt;a href="http://www.wambot.org/"&gt;WAMbot robot&lt;/a&gt; was &lt;a href="http://eureka.australianmuseum.net.au/2AFE70D0-76D3-11E0-A87E005056B06558?DISPLAYENTRY=true"&gt;selected as a finalist to the Eureka prize&lt;/a&gt; (Australia's top science prize) in the defence category. The awards ceremony took place in Sydney, at the Hordern Pavilion. &lt;br /&gt;&lt;br /&gt;It was an interesting event, showcasing the best of Australian science. Stiff competition meant the first place in the Defence category was snatched away by Prof Abdesselam Bouzerdoum who has done fantastic work in novel sensing systems.&lt;br /&gt;&lt;br /&gt;Maybe next time.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-1022910559989587659?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/1022910559989587659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=1022910559989587659' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/1022910559989587659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/1022910559989587659'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/09/eureka-prize-for-wambot.html' title='Eureka Prize for WAMbot'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-xWI6NnYnZZA/Tw2Vd796HMI/AAAAAAAAAdM/CDrH4okMzNc/s72-c/1103_WAMbot.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-978706745599763632</id><published>2011-09-06T21:06:00.000+08:00</published><updated>2012-01-12T21:51:31.060+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mining'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><title type='text'>AIMEX</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-ZoNDdtPhNt4/Tw7kY16pmDI/AAAAAAAAAdU/zHjGZ4kAza8/s1600/IMG_1618-small.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="150" src="http://1.bp.blogspot.com/-ZoNDdtPhNt4/Tw7kY16pmDI/AAAAAAAAAdU/zHjGZ4kAza8/s200/IMG_1618-small.JPG" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;I visited the &lt;a href="http://www.aimex.com.au/"&gt;Asia-Pacific International Mining Exhibition (AIMEX)&lt;/a&gt;, held every four years. There was a lot of interesting technology on display, with a strong presence of simulators, drills and long-wall gear. Being mining, a lot of very large machines were on display, and the exhibition hall was huge. Automation also had a small presence.&lt;br /&gt;&lt;br /&gt;Atlas-Copco had a set of their autonomous drill rig simulators on display, and I managed to get a chance to go through the process. Drilling is a non-trivial task, and it takes at least two weeks for an operator to familiarize themselves with the process. The autonomous drill system certainly makes it easier to operate the equipment, but the drill holes still have to be lined up manually - arguably the most challenging task.&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-HKpk_kj2Avw/Tw7kf4M7euI/AAAAAAAAAdc/xfKiHxwrzRo/s1600/IMG_1621-small.JPG" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="150" src="http://1.bp.blogspot.com/-HKpk_kj2Avw/Tw7kf4M7euI/AAAAAAAAAdc/xfKiHxwrzRo/s200/IMG_1621-small.JPG" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Atlas Copco Autonomous Drill console&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Eickhoff had a demonstration of their automated long-wall system, that uses the &lt;a href="http://indurad.com/"&gt;Indurad&lt;/a&gt; radar system. &lt;br /&gt;&lt;br /&gt;CAT were displaying some of their new autonomous equipment, soon to be installed in &lt;br /&gt;&lt;a href="http://www.miningaustralia.com.au/news/cat-sign-autonomous-truck-deal-with-fortescue"&gt;Western Australia at FMG's Solomon mine&lt;/a&gt;. CAT is always a slow mover to adopt technology but it is interesting to see how fast this technology is being adopted by the major Australian miners, now including Rio Tinto, BHP, Newcrest and FMG.&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-9Dnqjeh-QTc/Tw7kvfTN8LI/AAAAAAAAAdk/bbkjvO1pnOs/s1600/IMG_1626-small.JPG" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="150" src="http://3.bp.blogspot.com/-9Dnqjeh-QTc/Tw7kvfTN8LI/AAAAAAAAAdk/bbkjvO1pnOs/s200/IMG_1626-small.JPG" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Eickhoff longwall automation&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Below is a video of the CAT system I captured at AIMEX. Apparently this system actually does realtime path planning and adjustment as opposed to following a pre-programmed path like other (Sandvik) systems.&lt;br /&gt;&lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/NMXe-TRmz14" width="420"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;You can watch some more videos of autonomous mine vehicles on youtube:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=fLngT2Si1SY"&gt;CAT 'command' system for haul trucks&lt;/a&gt; and &lt;a href="http://www.youtube.com/watch?v=-Y1xgkavUrw"&gt;MineGem&lt;/a&gt;. (See &lt;a href="http://research.ict.csiro.au/research/labs/autonomous-systems/field-robotics/mining-robotics/load-haul-dump-lhd-automation"&gt;CSIRO's work on LHD&lt;/a&gt;)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=ShBMIoQk6Wc"&gt;Atlas-Copco scooptram for loaders&lt;/a&gt; (See &lt;a href="http://msl.mine.queensu.ca/groups/msl/wiki/88cfa/Joshua_Marshall.html"&gt; Joshua Marshall's work on Scooptram&lt;/a&gt;)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=AnK2AkTcFjI"&gt;Sanvik Automine for loaders&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-978706745599763632?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/978706745599763632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=978706745599763632' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/978706745599763632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/978706745599763632'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/06/aimex.html' title='AIMEX'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-ZoNDdtPhNt4/Tw7kY16pmDI/AAAAAAAAAdU/zHjGZ4kAza8/s72-c/IMG_1618-small.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-9222648737027954569</id><published>2011-09-04T20:13:00.000+08:00</published><updated>2011-09-04T20:13:04.633+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><title type='text'>Mozilla Demopart - The Self Explanatory Demo</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-_QXsoSZWDEo/TmNrNegNLsI/AAAAAAAAAcI/1W9dtfMgfoA/s1600/helperslide384.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/-_QXsoSZWDEo/TmNrNegNLsI/AAAAAAAAAcI/1W9dtfMgfoA/s200/helperslide384.jpg" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;The Self-Explanatory Demo&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;With the help of Chris Mylrae (music) I put together a last minute entry to the Mozilla Demoparty demo competition. You can see our entry &lt;a href="https://demoparty.mozillalabs.com/gallery/88/the-self-explanatory-demo"&gt;The Self Explanatory Demo&lt;/a&gt;. It derives and explains a number of oldschool demoscene effects, including the XOR bitplasma, sin/cos plasma, ripples, inteference, and tunnel effect. It also shows the origin of equations for radius of a circle, sine and cosine, tan and arctan, and 3d projection. In essence, it is an animated version of the demo effect explanations on this blog.&lt;br /&gt;&lt;br /&gt;Overall, the demo placed in &lt;a href="http://mozillalabs.com/blog/2011/09/we-got-the-winners"&gt;third place in the html5 WebGL demo competition&lt;/a&gt;. The &lt;a href="https://demoparty.mozillalabs.com/gallery/81/webgl-water"&gt;winning single-effect entry WebGL water&lt;/a&gt; is well worth a look.&lt;br /&gt;&lt;br /&gt;To put together my entry in the two days I had I used, &lt;a href="https://github.com/mrdoob/three.js/"&gt;three.js&lt;/a&gt;.&lt;br /&gt;There is now a new &lt;a href="http://learningthreejs.com/"&gt;tutorial site for three.js&lt;/a&gt;, it is definitely worth taking a look at.&lt;br /&gt;&lt;br /&gt;Finally, I'll leave you with an amazing 64k production, 'uncovering static' by Fairlight and Alcatraz.&lt;br /&gt;&lt;iframe allowfullscreen="" frameborder="0" height="345" src="http://www.youtube.com/embed/69Xjc7eklxE" width="560"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-9222648737027954569?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/9222648737027954569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=9222648737027954569' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/9222648737027954569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/9222648737027954569'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/09/mozilla-demopart-self-explanatory-demo.html' title='Mozilla Demopart - The Self Explanatory Demo'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-_QXsoSZWDEo/TmNrNegNLsI/AAAAAAAAAcI/1W9dtfMgfoA/s72-c/helperslide384.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-543206240741647877</id><published>2011-08-16T21:51:00.001+08:00</published><updated>2011-08-16T21:54:32.594+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><title type='text'>Kinect and OpenKinect on Apple Mac OSX</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-FItok8i53cU/Tkp02JV0ifI/AAAAAAAAAcA/qOUeo7yUX34/s1600/Screen+shot+2011-08-07+at+9.57.48+AM.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="151" src="http://4.bp.blogspot.com/-FItok8i53cU/Tkp02JV0ifI/AAAAAAAAAcA/qOUeo7yUX34/s200/Screen+shot+2011-08-07+at+9.57.48+AM.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Adrian, in Kinect-3D!&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;The Kinect is a revolutionary sensor for robotics - the low price point has seen an explosion of interest and applications in this field. (Hopefully we will see the same for the &lt;a href="http://www.neatorobotics.com/"&gt;Neato XV11 low cost laser scanner&lt;/a&gt; one day). I was very impressed by the data the Kinect returned, it is a fantastic device. &lt;br /&gt;&lt;br /&gt;To get started, just follow the &lt;a href="http://openkinect.org/wiki/Getting_Started#OS_X"&gt;OSX install instructions at OpenKinect&lt;/a&gt;. You will need &lt;a href="http://www.macports.org/"&gt;MacPorts&lt;/a&gt;. A copy of the instructions is here:&lt;br /&gt;&lt;pre&gt;sudo port install git-core&lt;br /&gt;sudo port install libtool&lt;br /&gt;sudo port install libusb-devel&lt;br /&gt;git clone https://github.com/OpenKinect/libfreenect.git&lt;br /&gt;cd libfreenect&lt;br /&gt;mkdir build&lt;br /&gt;cd build&lt;br /&gt;ccmake ..&lt;br /&gt;cmake ..&lt;br /&gt;make&lt;br /&gt;sudo make install&lt;br /&gt;&lt;/pre&gt;(Press 'g' to generate your cmake make files). Very simple.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-zZyXWHP3qAk/Tkp0tQHABoI/AAAAAAAAAb8/wvexG3_HunQ/s1600/Screen+shot+2011-08-07+at+10.22.34+AM.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-zZyXWHP3qAk/Tkp0tQHABoI/AAAAAAAAAb8/wvexG3_HunQ/s1600/Screen+shot+2011-08-07+at+10.22.34+AM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Now check under system profiler to see that the Kinect device is detected.&lt;br /&gt;&lt;br /&gt;I had the following error when I tried to read from the device:&lt;br /&gt;&lt;pre&gt;Isochronous transfer error: 1 &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Thankfully, this was easy to solve with a fully self-contained installer from &lt;a href="http://www.as3kinect.org/download/"&gt;AS3 kinect OSX download package&lt;/a&gt;. You should now be able to read the color image, depth map, and command the servo.&lt;br /&gt;&lt;br /&gt;The next step will likely be to interpret the data in some form. The &lt;a href="http://pointclouds.org/"&gt;Point Cloud Library&lt;/a&gt; will be very useful for processing the data. A &lt;a href="http://www.pointclouds.org/media/rss2011.html"&gt;tutorial on Point Cloud Library&lt;/a&gt; is available, although many features are breezed over.&lt;br /&gt;&lt;br /&gt;But to begin with PCL, you will need Eigen, a fast vector and matrix math library. (Also used in MRPT)&lt;br /&gt;First &lt;a href="http://eigen.tuxfamily.org/index.php?title=Main_Page#Download"&gt;download Eigen&lt;/a&gt;, and unzip it. Building Eigen is quite straight forward:&lt;br /&gt;&lt;pre&gt;cd eigen-eigen-3.0.1&lt;br /&gt;mkdir build&lt;br /&gt;cd build/&lt;br /&gt;cmake ../&lt;br /&gt;sudo make install&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;PCL has a self installing package, and will install itself to /usr/local/lib/libpcl_*&lt;br /&gt;Here is a simple test program from the tutorial:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="p1"&gt;&lt;span class="s1"&gt;#include &lt;/span&gt;&lt;iostream&gt;&lt;/iostream&gt;&lt;/div&gt;&lt;div class="p1"&gt;&lt;span class="s1"&gt;#include &lt;/span&gt;"pcl/io/pcd_io.h"&lt;span class="s1"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div class="p1"&gt;&lt;span class="s1"&gt;#include &lt;/span&gt;"pcl/point_types.h"&lt;span class="s1"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="s2"&gt;int&lt;/span&gt; main (&lt;span class="s2"&gt;int&lt;/span&gt; argc, &lt;span class="s2"&gt;char&lt;/span&gt;** argv) {&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; pcl::PointCloud&lt;pcl::pointxyz&gt; cloud;&amp;nbsp;&lt;/pcl::pointxyz&gt;&lt;/div&gt;&lt;div class="p4"&gt;&lt;span class="s3"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;//Fill the cloud data&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; cloud.width = &lt;span class="s4"&gt;5&lt;/span&gt;;&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; cloud.height = &lt;span class="s4"&gt;1&lt;/span&gt;;&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; cloud.is_dense = &lt;span class="s2"&gt;false&lt;/span&gt;;&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; cloud.points.resize(cloud.width * cloud.height);&amp;nbsp;&lt;/div&gt;&lt;div class="p2"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="s2"&gt;for&lt;/span&gt; (size_t i = &lt;span class="s4"&gt;0&lt;/span&gt;; i &amp;lt; cloud.points.size(); ++i) {&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; cloud.points[i].x = &lt;span class="s4"&gt;1024&lt;/span&gt; * rand() / (RAND_MAX + &lt;span class="s4"&gt;1.0&lt;/span&gt;);&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; cloud.points[i].y = &lt;span class="s4"&gt;1024&lt;/span&gt; * rand() / (RAND_MAX + &lt;span class="s4"&gt;1.0&lt;/span&gt;);&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; cloud.points[i].z = &lt;span class="s4"&gt;1024&lt;/span&gt; * rand() / (RAND_MAX + &lt;span class="s4"&gt;1.0&lt;/span&gt;);&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp;&lt;/div&gt;&lt;div class="p2"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; pcl::io::savePCDFileASCII(&lt;span class="s5"&gt;"test_pcd.pcd"&lt;/span&gt;, cloud);&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; std::cerr &amp;lt;&amp;lt; &lt;span class="s5"&gt;"Saved "&lt;/span&gt; &amp;lt;&amp;lt; cloud.points.size () &amp;lt;&amp;lt; &lt;span class="s5"&gt;" data points to test_pcd.pcd. "&lt;/span&gt; &amp;lt;&amp;lt; std::endl;&amp;nbsp;&lt;/div&gt;&lt;div class="p2"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="s2"&gt;for&lt;/span&gt; (size_t i = &lt;span class="s4"&gt;0&lt;/span&gt;; i &amp;lt; cloud.points.size(); ++i)&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; std::cerr &amp;lt;&amp;lt; &lt;span class="s5"&gt;"&amp;nbsp; &amp;nbsp; "&lt;/span&gt; &amp;lt;&amp;lt; cloud.points[i].x &amp;lt;&amp;lt; &lt;span class="s5"&gt;" "&lt;/span&gt; &amp;lt;&amp;lt; cloud.points[i].y &amp;lt;&amp;lt; &lt;span class="s5"&gt;" "&lt;/span&gt; &amp;lt;&amp;lt; cloud.points[i].z &amp;lt;&amp;lt; std::endl;&amp;nbsp;&lt;/div&gt;&lt;div class="p2"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="s2"&gt;return&lt;/span&gt;(&lt;span class="s4"&gt;0&lt;/span&gt;);&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;}&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This can be compiled directly with:&lt;br /&gt;&lt;pre&gt;g++ pcd_write.cpp -c -I /usr/local/include/pcl-1.0/ -I /usr/local/include/eigen3/ &lt;br /&gt;g++ pcd_write.o /usr/local/lib/libpcl_io.dylib &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally, attached is a youtube video showing some very impressive visual SLAM surface reconstruction with the Kinect (See &lt;a href="http://research.microsoft.com/en-us/projects/surfacerecon/"&gt;KinectFusion project page&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/quGhaggn3cQ" width="560"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;br /&gt;Of course, you will probably want some image stabilization technology to get smooth input videos, so why not try an Owl?&lt;br /&gt;&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/9hBpF_Zj4OA" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Happy Hacking!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-543206240741647877?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/543206240741647877/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=543206240741647877' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/543206240741647877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/543206240741647877'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/08/kinect-and-openkinect-on-apple-mac-osx.html' title='Kinect and OpenKinect on Apple Mac OSX'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-FItok8i53cU/Tkp02JV0ifI/AAAAAAAAAcA/qOUeo7yUX34/s72-c/Screen+shot+2011-08-07+at+9.57.48+AM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-8090447872665293973</id><published>2011-08-12T13:45:00.000+08:00</published><updated>2011-08-12T13:45:06.919+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><title type='text'>ROS - Robot Operating System</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-b7_p2niBH4M/TkS9ZXGxaCI/AAAAAAAAAb4/KYB3LhkyC6s/s1600/ros.org.640w.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="73" src="http://3.bp.blogspot.com/-b7_p2niBH4M/TkS9ZXGxaCI/AAAAAAAAAb4/KYB3LhkyC6s/s320/ros.org.640w.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Not so long ago there were a number of robotics packages that provided a variety of functionality of various tasks, such as OpenCV for computer vision, MRPT for mobile robots and ORCOS for general functions. Recently, this has changed as Robot Operating System (ROS) has become the predominant system which has swallowed the functionality of all the other packages.&lt;br /&gt;&lt;br /&gt;ROS functionality includes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Support for various sensors and robots including Neato XV-11, Roomba, IRobot, Pioneer/ARIA, Nao, Android, KUKA, Sick, Hokuyo, Bumblebee, Firewire cameras, Webcameras, Xsens, Wiimote, EtherCAT, CAN &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Support for a number of other libraries/packages including CUDA, OpenCV, Eigen, PCL, SVM/Bayesian, Spatial subdivision, OGRE, XML, and many more. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.ros.org/news/2011/01/open-motion-planning-library-ompl-released.html"&gt;Motion planning library for mobile robots&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.ros.org/wiki/3d_navigation"&gt;3d Navigation stack&lt;/a&gt; &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.ros.org/news/2011/01/inverse-dynamics-and-dynamics-markers.html"&gt;Inverse dynamics for robotic manipulators with calibration points&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;SLAM packages including &lt;a href="http://www.ros.org/wiki/graph_mapping"&gt;Graph SLAM&lt;/a&gt; (see &lt;a href="http://www.ros.org/wiki/laser_slam"&gt;Laser SLAM&lt;/a&gt;), &lt;a href="http://www.ros.org/wiki/openni/Contests/ROS%203D/RGBD-6D-SLAM"&gt;RGBD 6D SLAM&lt;/a&gt; and &lt;a href="http://www.ros.org/wiki/vslam"&gt;Spares visual SLAM&lt;/a&gt; (also &lt;a href="http://www.ros.org/wiki/ScaViSLAM"&gt;ScaViSLAM&lt;/a&gt;)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.ros.org/wiki/twoLevelMTTD_stack"&gt;Multi target tracking&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;People detection with &lt;a href="http://www.ros.org/wiki/people_experimental"&gt;laser (leg)&lt;/a&gt; and &lt;a href="http://www.ros.org/wiki/ppl_detection"&gt;vision&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Physics engines including ODE and Bullet, and the Gazebo and OpenRAVE simulators and COLLADA loaders. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.ros.org/wiki/Events/CoTeSys-ROS-School"&gt;ROS functionality overview at the CoTeSys ROS school&lt;/a&gt; held at the Technical University Munich (my old visiting University).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Refer to this &lt;a href="http://www.ros.org/browse/list.php"&gt;full list of ROS packages&lt;/a&gt;. The functionality encapsulated by ROS is both amazing and disturbing.&lt;br /&gt;&lt;br /&gt;I've never been a fan of massive (disorganised!) frameworks that force a work structure onto you, but the robotics world isn't leaving you with much choice anymore. After implementing a graph based information flow architecture in &lt;a href="http://improvcv.sourceforge.net"&gt;ImprovCV&lt;/a&gt; and working closely with DirectShow's graphfilter I'm also keenly aware of the limitations of a graph-based approach to software development. It's not a one-size-fits-all solution, unfortunately ROS leaves little choice.&lt;br /&gt;&lt;br /&gt;Thankfully some ROS packages are largely stand alone, so there is still some hope that one day some organisation will put in the effort to streamline and clean up ROS overall.&lt;br /&gt;&lt;br /&gt;In any case getting ROS running on Apple Mac OSX 10.6 was not too difficult, however I lost my install notes in an untimely crash, so I'll only give a brief overview. ROS installation relies on MacPorts. I'd been holding off on installing MacPorts as it has historically been unstable, and doesn't play nicely with already installed libraries. MacPorts is now stable and well tested, but it still doesn't play nice with the rest of your system.&lt;br /&gt;&lt;br /&gt;To install ROS I followed the &lt;a href="http://www.ros.org/wiki/diamondback/Installation/OSX"&gt;ROS diamondback OSX installation instructions&lt;/a&gt;, all without any major dramas. I did have to alter the CMakeLists.txt as suggested in the troubleshooting section.&lt;br /&gt;&lt;br /&gt;MacPorts gave me a few headaches, some of the errors I encountered were: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Error: Target org.macports.install returned: no destroot found&lt;br /&gt;&lt;br /&gt;To solve, use: &lt;pre&gt;sudo port clean NAME&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Error: NAME&amp;nbsp;already exists and does not belong to a registered port&lt;br /&gt;&lt;br /&gt;To solve, use:&lt;pre&gt;sudo port -f activate NAME&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Once ROS is all installed you can source setup.sh. Remember to add in any additional packages to ROS_PACKAGE_PATH.&lt;br /&gt;&lt;br /&gt;All in all, I wouldn't recommend running ROS on OSX, although the base ROS install works without any major dramas, installing each individual package is a bit of a struggle. &lt;br /&gt;&lt;br /&gt;I believe ROS is an appropriate name, it really should be a stand alone operating system. I would strongly advise setting up a separate linux OS dedicated to your ROS install, running ROS ontop of OSX is quite problematic.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-8090447872665293973?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/8090447872665293973/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=8090447872665293973' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8090447872665293973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8090447872665293973'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/08/ros-robot-operating-system.html' title='ROS - Robot Operating System'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-b7_p2niBH4M/TkS9ZXGxaCI/AAAAAAAAAb4/KYB3LhkyC6s/s72-c/ros.org.640w.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-8775154974417922539</id><published>2011-08-10T19:58:00.001+08:00</published><updated>2011-08-10T21:42:49.658+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Communications and Messaging Frameworks</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-NoZmOSbaD_c/TkJyQpi07KI/AAAAAAAAAb0/sR8yJINsl2g/s1600/msgq.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="134" src="http://3.bp.blogspot.com/-NoZmOSbaD_c/TkJyQpi07KI/AAAAAAAAAb0/sR8yJINsl2g/s200/msgq.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;A common problem for any distributed software project is handling inter process communications and messaging. Luckily, a number of frameworks already exist to solve this issue. Robotics projects tend to have a range of requirements, from providing a higher level cognitive architecture framework (typically a set of interacting components or nodes) to low-level realtime communications (e.g. CANbus, RT ethernet).&lt;br /&gt;&lt;br /&gt;Some robotics packages already provide a particular architecture, such as ImprovCV and ROS which are both filter based, or MRPT which provides some IPC primitives. However, this problem is hardly limited to robotics and many real time distributed networking/processing systems have similar communications requirements. (e.g. computer games, or traffic management systems / plant control systems).&lt;br /&gt;&lt;br /&gt;The communications frameworks can be broadly grouped into three categories:&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Integrated middlewear for a larger package&lt;br /&gt;&lt;/li&gt;&lt;li&gt; (hard) Real time control orientated frameworks&lt;br /&gt;&lt;/li&gt;&lt;li&gt; (soft) Real time messaging libraries&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;From a games perspective, the people at second life have a nice &lt;a href="http://wiki.secondlife.com/wiki/Message_Queue_Evaluation_Notes"&gt; evaluation of several messaging systems&lt;/a&gt;.   Beginning with soft real time messaging, some interesting libraries include: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/protobuf/"&gt; Google protocol buffers&lt;/a&gt;, for serialisation. I mention it, because it is popular.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://msgpack.org/"&gt;MessagePack&lt;/a&gt; is a language agnostic message serialisation system similar to Google protocol buffers - just faster and better.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.omg.org/spec/CORBA/"&gt;CORBA&lt;/a&gt; allows objects to be sent around a network, often used in business applications. It is an open standard and language agnostic as it includes an Interface Definition Language to define components.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Distributed_Component_Object_Model"&gt;Microsoft DCOM / .NET remote&lt;/a&gt; and its many variants are similar to CORBA, just the Microsoft variant.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Apache &lt;a href="http://activemq.apache.org/"&gt;ActiveMQ&lt;/a&gt; another enterprise orientated message broker with support for a large number of scripting languages (Python, PHP, Ruby, Perl, etc).&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.jenkinssoftware.com/"&gt;RakNet&lt;/a&gt; manages distributed objects, primarily targeted towards computer games (used in Unity).&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://sourceforge.net/projects/opentnl/"&gt;Open Torque Networking Library&lt;/a&gt; has its origins in the Torque game engine designed for massively multiplayer games.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.inspirel.com/yami4/"&gt;YAMI4&lt;/a&gt; is a fairly advanced but easy to use peer to peer messaging framework for control systems that is easy to extend to a pub/sub system. POSIX, Windows, Java, C++, well worth a look. &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.zeromq.org/"&gt;0MQ&lt;/a&gt;, zero MQ is a messaging system that is socket based, and also has pub/sub extensions.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://socket.io/"&gt;Socket.IO&lt;/a&gt; hardly qualifies for a framework, but is a great enabler for realtime HTML communications, so it certainly deserves a mention.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;there are many more networking libraries available, but these are the ones that stand out for this category.  For hard real-time control tasks the choices are a bit more limited, however libraries of note are: &lt;ul&gt;&lt;li&gt;&lt;a href="http://www.blogger.com/post-create.g?blogID=17188375"&gt;Real time CORBA&lt;/a&gt;, is CORBA modified to be a bit more lightweight and able to support real time requirements. TAO ACE is worth looking into if your following this path.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://portals.omg.org/dds/"&gt;Data Distribution Service (DDS)&lt;/a&gt; is similar to Real time CORBA, however it has the advantage of lessons learnt from CORBA and provides simpler fine grained control over quality of service and intelligent networking. &lt;a href="http://www.rti.com/"&gt;RTI DDS&lt;/a&gt; is the framework we used for the WAMbot TARDEC/DSTO MAGIC 2010 project. &lt;a href="http://www.opendds.org/"&gt;OpenDDS&lt;/a&gt; is an open source implementation.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.blogger.com/post-create.g?blogID=17188375"&gt;Real time data base (RTDB)&lt;/a&gt; is an open source framework that provides a lower-level communications interface for C/C++ over Xenomai.  This is the framework we used for the Team Annieway entry to the DARPA Urban Challenge.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/lcm/"&gt;LCM&lt;/a&gt; is a socket-based IPC library used by Team Michigan for MAGIC 2010.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.cs.cmu.edu/~ipc/"&gt;IPC&lt;/a&gt; a low level inter process communications system for embedded systems used by NASA.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.blogger.com/post-create.g?blogID=17188375"&gt;Dynamic Data eXchange (DDX)&lt;/a&gt; is a large open source distributed software architecture developed by CSIRO and has been previously integrated with ROS.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Finally, there are a number of application specific frameworks, for Robotics this includes &lt;a href="http://www.ros.org/wiki/"&gt;ROS&lt;/a&gt;, MS Robot Studio, Player/Stage, &lt;a href="http://active-ist.sourceforge.net/jaus++.php"&gt;JAUS&lt;/a&gt; and more general packages such as Labview and Matlab.I think it is prudent for every software developer to be familiar with at least three tiers of communications frameworks, from large scale frameworks (e.g. CORBA) to light-weight frameworks (e.g. RackNet) to low-level frameworks (e.g. Socket.IO). Ideally, one for each key application area (e.g. Hard real time, Soft real time, Business applications, Web).&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-8775154974417922539?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/8775154974417922539/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=8775154974417922539' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8775154974417922539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8775154974417922539'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/08/communications-and-messaging-frameworks.html' title='Communications and Messaging Frameworks'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-NoZmOSbaD_c/TkJyQpi07KI/AAAAAAAAAb0/sR8yJINsl2g/s72-c/msgq.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-5453803237873129799</id><published>2011-07-29T13:13:00.000+08:00</published><updated>2011-07-29T13:13:57.942+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='compilers'/><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='education'/><category scheme='http://www.blogger.com/atom/ns#' term='raytracing'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='GPGPU'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><title type='text'>Half year catchup on Graphics, GPUs, Compilers, etc.</title><content type='html'>Another slow month on the blog. More than half way through the year, so its time to catch up on the backlog of news. Only covering graphics, games, physics and GPGPU and compilers. Expect a number of posts on robotics soon!&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.h-online.com/open/news/item/Report-GitHub-more-popular-than-SourceForge-and-Google-Code-1254752.html"&gt;GitHub is now more popular than SourceForge&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;&lt;a href="http://fgiesen.wordpress.com/2011/07/09/a-trip-through-the-graphics-pipeline-2011-index/"&gt;Fabian 'ryg' Giesen&lt;/a&gt; has put together an in-depth explanation of the graphics hardware pipeline.&lt;br /&gt;&lt;li&gt;nVidia released an extension to allow &lt;a href="http://developer.download.nvidia.com/opengl/specs/WGL_NV_DX_interop.txt"&gt;OpenGL direct access to DirectX buffers&lt;/a&gt;. Now you can write your graphics programs in both OpenGL and DirectX - pick whichever is easiest.&lt;br /&gt;&lt;li&gt;&lt;a href="http://developer.nvidia.com/nvidia-graphics-sdk-11-direct3d"&gt;nVidia released their 11th Graphics SDK&lt;/a&gt; - DirectX 11 only.&lt;br /&gt;&lt;li&gt;Aras did a blog post on &lt;a href="http://aras-p.info/blog/2011/05/03/a-way-to-visualize-mip-levels/?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed%3A+LostInTheTriangles+%28Lost+in+the+triangles%29"&gt;visualising mip-map levels&lt;/a&gt; and released the code to his shader.&lt;br /&gt;&lt;li&gt;Redirect OpenGL from a remote machine with this &lt;a href="https://visualization.hpc.mil/wiki/VirtualGL"&gt;VirtualGL tutorial&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.iryoku.com/mlaa/"&gt;Morphological Anti-Aliasing&lt;/a&gt; paper with source code.&lt;br /&gt;&lt;li&gt;Tim Lottes released his &lt;a href="http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html"&gt;FXAA anti-aliasing source code&lt;/a&gt;&lt;br /&gt;&lt;li&gt;José María Méndez wrote a fantastic article on &lt;a href="http://www.gamedev.net/page/resources/_/reference/programming/140/lighting-and-shading/a-simple-and-practical-approach-to-ssao-r2753"&gt;a simple method to implement screen space ambient occlusion&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;Improve your ambient occlusion with &lt;a href="http://badsector.posterous.com/dynamic-shading-using-precalculated-occlusion"&gt;occlusion normals&lt;/a&gt; to enable dynamic shading. &lt;br /&gt;&lt;li&gt;&lt;a href="http://mmmovania.blogspot.com/2011/02/c-class-for-glslshader.html"&gt;A simple GLSLShader handling class&lt;/a&gt;&lt;br /&gt;&lt;li&gt;Dave has a post on how you can &lt;a href="http://www.pawfal.org/dave/blog/2011/01/making-game-characters-with-a-webcam/"&gt;generate game characters with a webcam&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;&lt;a href="http://gamedevelopmenttools.com/index_Page348.htm"&gt;Source code from the Game Development Tools book&lt;/a&gt;. From texture generation and CSG to Continuous Integration, Perforce and XML. &lt;br /&gt;&lt;li&gt;Steven Wittens has a fantastic &lt;a href="http://acko.net/blog/making-planets"&gt;series of posts on procedurally generating planets and worlds&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;Amit's blog post on &lt;a href="http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/"&gt;polygon map generation&lt;/a&gt; using Voroni and Delaunay is worth a read.&lt;br /&gt;&lt;li&gt;The old game&lt;a href="http://www.ultimaaiera.com/galleries/ultima-6-technical-documents/"&gt;Ultima 6 technical documents&lt;/a&gt; have been released. An interesting look at game design and programming decisions made in 1990. This should help &lt;a href="http://nuvie.sourceforge.net/"&gt;nuvie&lt;/a&gt;, which has already made great progress.&lt;br /&gt;&lt;li&gt;Oldskool demoscener Trixter wrote an interesting post on&lt;a href="http://trixter.oldskool.org/2011/06/04/at-a-disadvantage/"&gt;C64 vs IBM PC&lt;/a&gt;, and argues the C64 was a faster computer.&lt;br /&gt;&lt;li&gt;Democoder Ferris/YUP did an interesting post on&lt;br /&gt;&lt;a href="http://yupferris.blogspot.com/2011/05/milk-and-compressors.html"&gt;creating a tiny 1k graphics demo&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;John Ratcliff updated his &lt;a href="http://codesuppository.blogspot.com/2011/07/revision-to-testhacd.html"&gt;Hierarchical Approximate Convex Decomposition utility library&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;Tim Ventimiglia and Kevin Wayne did an interesting post on&lt;a href="http://arborjs.org/docs/barnes-hut"&gt;using the Barnes-Hut algorithm to accelerate n-body simulations&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;Pierre Terdiman has a great post on &lt;a href="http://www.codercorner.com/blog/?p=461"&gt;fast separating axis tests&lt;/a&gt; to speed up your collision detection for convex objects.&lt;br /&gt;&lt;li&gt;&lt;a href="http://physbam.stanford.edu/links/getcode.html"&gt;PhysBAM source code&lt;/a&gt; - there is plenty of great stuff in here, so I'm sure to do a whole blog post on this later. It covers maths (e.g. ODEs, fourier transforms), spatial subdivision (KD trees, octrees), collision detection, raytracing and so much more.&lt;br /&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/opencloth/"&gt;OpenCloth&lt;/a&gt; is a new library for cloth simulation algorithms.&lt;br /&gt;&lt;li&gt;&lt;a href="http://developer.nvidia.com/apex"&gt;nVidia APEX SDK&lt;/a&gt; is now free. It has a number of functions that help with clothing and destruction physics.&lt;br /&gt;&lt;li&gt;&lt;a href="http://supportcenteronline.com/ics/support/default.asp?deptID=1949"&gt;PhysxLab&lt;/a&gt; is a digital content creation tool to help you take advantage of the APEX sdk destruction features.&lt;br /&gt;&lt;li&gt;The Oren Game Engine blog has a great post on&lt;a href="http://orenk2k.blogspot.com/2010/03/real-time-destructionfractures.html"&gt;implementing destruction fractures&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;A &lt;a href="http://users.softlab.ece.ntua.gr/~ttsiod/cudarenderer.html"&gt;realtime raytracer with pure C++, OpenMP and CUDA&lt;/a&gt; written by Thanassis Tsiodras is accompanied by some interesting analysis.&lt;br /&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/vcblog/archive/2011/06/15/introducing-amp.aspx"&gt;Microsoft Accelerated Massive Parallelism (C++ AMP)&lt;/a&gt; appears to be the microsoft attempt at competing with CUDA, OpenCL and some of the libraries ontop of those technologies.&lt;br /&gt;&lt;li&gt;Microsoft also released &lt;a href="http://blogs.msdn.com/b/vcblog/archive/2011/02/03/10124642.aspx"&gt;concurrent containers&lt;/a&gt;, parallel versions of STL algorithms.&lt;br /&gt;&lt;li&gt;&lt;a href="http://webcl.nokiaresearch.com/"&gt;WebCL&lt;/a&gt; - OpenCL for the web, at Nokia research.&lt;br /&gt;&lt;li&gt;&lt;a href="http://developer.amd.com/zones/OpenCLZone/universities/Pages/default.aspx"&gt;AMD's OpenCL University kit&lt;/a&gt; covers some OpenCL and GPU basics.&lt;br /&gt;&lt;li&gt;&lt;a href="http://developer.amd.com/sdks/amdappsdk/pages/default.aspx"&gt;AMD Accelerated Parallel Processing (APP) SDK (formerly ATI Stream) &lt;/a&gt; has had a few updates, currently 2.4 is out.&lt;br /&gt;&lt;li&gt;&lt;a href="http://developer.amd.com/tools/gDEBugger/Pages/default.aspx"&gt;AMD gDEBugger&lt;/a&gt; is now free for debugging OpenGL and OpenCL programs.&lt;br /&gt;&lt;li&gt;&lt;a href="http://ispc.github.com/"&gt;Intel SPMD Program Compiler&lt;/a&gt; is designed to generate optimal SIMD programs from a C-like language.&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.pathscale.com/ekopath4-open-source-announcement"&gt;PathScale EKOPath 4&lt;/a&gt; is an optimising compiler, now free for linux, BSD and Solaris.&lt;br /&gt;&lt;li&gt;Yang Chen wrote an amazing post &lt;a href="http://blog.regehr.org/archives/320"&gt;comparing compiler optimizations&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;&lt;a href="http://offbytwo.com/2011/06/26/things-you-didnt-know-about-xargs.html"&gt;Helpful hints on the unix command xargs&lt;/a&gt; &lt;br /&gt;&lt;li&gt;&lt;a href="http://freearc.org/Default.aspx"&gt;FreeArc&lt;/a&gt; is an amazing open source compressor. Fast and fantastic compression ratios.&lt;br /&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/google-diff-match-patch/"&gt;Google's excellent diff/match/patch tools&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html"&gt;Visual hashing explained&lt;/a&gt;, how to detect similar images.&lt;br /&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/ocropus/"&gt;Ocropus&lt;/a&gt; is a open source library for Optical Character Recognition (OCR).&lt;br /&gt;&lt;/ul&gt;Finally, here is the SIGGRAPH 2011 technical papers highlights video, it contains a number of interesting advances in physics simulations and modeling.&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/JK9EEE3RsKM" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-5453803237873129799?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/5453803237873129799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=5453803237873129799' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5453803237873129799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5453803237873129799'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/07/half-year-catchup-on-graphics-gpus.html' title='Half year catchup on Graphics, GPUs, Compilers, etc.'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/JK9EEE3RsKM/default.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-3409600758537964570</id><published>2011-06-27T13:14:00.004+08:00</published><updated>2011-07-18T16:05:12.180+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><title type='text'>CAD on OSX with Blender and Rhino - DWG</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-jh9d2QLATJI/Tgg07QpEnTI/AAAAAAAAAaM/6EE4RlnKAXY/s1600/rhinomac.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="102" src="http://1.bp.blogspot.com/-jh9d2QLATJI/Tgg07QpEnTI/AAAAAAAAAaM/6EE4RlnKAXY/s200/rhinomac.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;The majority of the engineering world use AutoCAD-like products for creating drawings, with typical exchange formats of DWG, DXF, SAT or IGES. (I wrote some tips on &lt;a href="http://adrianboeing.blogspot.com/2010/08/cad-packages.html"&gt;using AutoCAD and SolidEdge here&lt;/a&gt;) Unfortunately on OSX there has been historically little choice. I asked &lt;a href="http://cad-3d.blogspot.com/"&gt;Stefan Boeykens who runs the CAD 3D blog&lt;/a&gt; for suggestions, and compiled a list of possibilities:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://usa.autodesk.com/adsk/servlet/pc/index?id=15421056&amp;amp;siteID=123112"&gt;AutoCAD&lt;/a&gt; have a Mac OSX version. Obviously 100% DWG support, the downside is the price (Retails for $3,995, 30 day trial)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.icadmac.com/"&gt;iCADmac&lt;/a&gt; is a mac port of progeCAD, that is actually very good on OSX (still a poorer cousin of AutoCAD). I use this for 2D CAD work on OSX. (Retails ~$1000, 30 day trial)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.graebert.com/en/cad/ares/103"&gt;ARES commander&lt;/a&gt; is a cross platform CAD package for Windows,OSX,Linux. So there should be no compatibility issues between. I've not tried it out myself. (Retails $795, 30 day trial)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.blender.org/"&gt;Blender&lt;/a&gt; is a free cross platform 3D package, that does have DWG/DXF plugin support. Unfortunately, the DWG support is not very good, and it is difficult to get the plugin to work under OSX and Linux. (free, Open Source)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.irhino3d.com/"&gt;Rhino 3D&lt;/a&gt;, a free trial version for OSX at the moment. (Retail expected ~$1000, free unrestricted trial while in beta)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Although Stefan mentioned some issues with Rhino3D, it worked perfectly with all my CAD files, and it is still an alpha product at the moment. Rhino3D supports a lot of file formats to a high standard: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;3dm (Rhino format)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;3ds (3d Studio, original not Max)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;dwg (AutoCAD - I tested the 2007 version)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;dxf (AutoCAD)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;fbx (MotionBuilder)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;iges (IGES)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;lwo (Lightwave)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;obj (Wavefront)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;sat (ACIS) [Export only]&lt;br /&gt;&lt;/li&gt;&lt;li&gt;stl (Stereolithography)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;vrml (VRML, also wrl file format)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;In the end, I only used Rhino3D to convert the data and used Blender for doing most of my data manipulation, as I already have a number of scripts for it (See &lt;a href="http://adrianboeing.blogspot.com/2010/10/convex-hull-generation-in-blender.html"&gt;Convex hull generation for Blender&lt;/a&gt;).   Every time I get back to using Blender after a pause it takes me a while to get used to the interface, here are some common commands I use when manipulating objects to conform to a given coordinate system: &lt;br /&gt;&lt;ul&gt;&lt;li&gt; space - add an object&lt;br /&gt;&lt;/li&gt;&lt;li&gt; g - move (follow by x,y,z to select an axis) &lt;br /&gt;&lt;/li&gt;&lt;li&gt; r - rotate (follow by x,y,z to select an axis)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; a - selects all objects&lt;br /&gt;&lt;/li&gt;&lt;li&gt;h - hide objects&lt;/li&gt;&lt;li&gt;. - zooms so you can see all&lt;br /&gt;&lt;/li&gt;&lt;li&gt;0 - switches to camera view (F9 - edit panel, you can set the FOV by altering 'D')&lt;/li&gt;&lt;li&gt;n - displays the current transformation matrix (To find the global coordinates you should view the Object in edit mode)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;SHIFT+c - centres the cursor&lt;br /&gt;&lt;/li&gt;&lt;li&gt;View-&gt;View properties - allows you to manually enter the cursor position&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Object-&amp;gt;Transform-&amp;gt;Center Cursor - allows you to re-define the center of the object&lt;br /&gt;&lt;/li&gt;&lt;li&gt;CTRL+a - collapses the rotation/scale transformation matrices. (see above for setting the position)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;CTRL+p - to parent objects, allowing you to move them in groups&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;This &lt;a href="http://www.katsbits.com/tutorials/blender/useful-keyboard-shortcuts.php"&gt;Blender keyboard shortcut map&lt;/a&gt; always comes in handy too!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-3409600758537964570?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/3409600758537964570/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=3409600758537964570' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3409600758537964570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3409600758537964570'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/06/cad-on-osx-with-blender-and-rhino-dwg.html' title='CAD on OSX with Blender and Rhino - DWG'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-jh9d2QLATJI/Tgg07QpEnTI/AAAAAAAAAaM/6EE4RlnKAXY/s72-c/rhinomac.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-778239073989261086</id><published>2011-06-17T22:48:00.003+08:00</published><updated>2011-06-17T22:49:43.259+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><title type='text'>Deform (textured interference) effect in WebGL</title><content type='html'>&lt;script id="shader-vs" type="x-shader/x-vertex"&gt;//===================================================================================//Vertex Shader//===================================================================================  attribute vec3 aVertexPosition;  void main(void) {    gl_Position = vec4(aVertexPosition, 1.0);  }&lt;/script&gt;&lt;br /&gt;&lt;script id="shader-fs" type="x-shader/x-fragment"&gt;#ifdef GL_ESprecision highp float;#endifuniform float time;uniform vec2 resolution;uniform vec4 mouse;uniform sampler2D tex0;uniform sampler2D tex1;void main(void){    vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;    vec2 offset1 = -1.0 + 2.0 * vec2(0.8,0.8);    vec2 offset2 = -1.0 + 2.0 * vec2(0.2,0.2);    float a1 = atan(p.y-offset1.y,p.x-offset1.x);    float r1 = sqrt(dot(p-offset1,p-offset1));    float a2 = atan(p.y-offset2.y,p.x-offset2.x);    float r2 = sqrt(dot(p-offset2,p-offset2));   vec2 uv;    uv.x = 0.2*time + (r1-r2)*0.25;    uv.y = sin(2.0*(a1-a2));    float w = r1*r2*0.8;    vec3 col = texture2D(tex0,uv).xyz;    gl_FragColor = vec4(col/(.1+w),1.0);}&lt;/script&gt;&lt;br /&gt;&lt;script id="simple-fs" type="x-shader/x-fragment"&gt;//===================================================================================//Fragment Shader//===================================================================================precision highp float;uniform vec2 resolution;uniform float time;void main(void){    gl_FragColor = vec4(gl_FragCoord.x / resolution.x, gl_FragCoord.y / resolution.y, time - floor(time), 1.0);}&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;//===================================================================================//Javascript code for setting up WebGL//===================================================================================  var canvas;  var startTime;   var gl;  var squareVertexPositionBuffer;  var shaderProgram;  var neheTexture;  function initGL(canvas) {    try {      gl = canvas.getContext("experimental-webgl");      gl.viewportWidth = canvas.width;      gl.viewportHeight = canvas.height;    } catch(e) {    }    if (!gl) {      alert("Could not initialise WebGL!");    }    startTime = (new Date()).getTime();  }  function getShader(gl, id) {    var shaderScript = document.getElementById(id);    if (!shaderScript) {      return null;    }    var str = "";    var k = shaderScript.firstChild;    while (k) {      if (k.nodeType == 3) {        str += k.textContent;      }      k = k.nextSibling;    }    var shader;    if (shaderScript.type == "x-shader/x-fragment") {      shader = gl.createShader(gl.FRAGMENT_SHADER);    } else if (shaderScript.type == "x-shader/x-vertex") {      shader = gl.createShader(gl.VERTEX_SHADER);    } else {      return null;    }    gl.shaderSource(shader, str);    gl.compileShader(shader);    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {      alert(gl.getShaderInfoLog(shader));      return null;    }    return shader;  }  function initShaders() {    var fragmentShader = getShader(gl, "shader-fs");    //var fragmentShader = getShader(gl, "simple-fs");    var vertexShader = getShader(gl, "shader-vs");    shaderProgram = gl.createProgram();    gl.attachShader(shaderProgram, vertexShader);    gl.attachShader(shaderProgram, fragmentShader);    gl.linkProgram(shaderProgram);    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {      alert("Could not initialise shaders");    }    gl.useProgram(shaderProgram);    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);    shaderProgram.pResolutionUniform = gl.getUniformLocation(shaderProgram, "resolution");    shaderProgram.pTimeUniform = gl.getUniformLocation(shaderProgram, "time");  }  function setUniforms() {     gl.activeTexture(gl.TEXTURE0);    gl.bindTexture(gl.TEXTURE_2D, neheTexture);    gl.uniform1i(shaderProgram.samplerUniform, 0);      gl.uniform2f(shaderProgram.pResolutionUniform, canvas.width, canvas.height);    var time = (new Date()).getTime();    gl.uniform1f(shaderProgram.pTimeUniform, (time - startTime) / 1000.0);  }  function initBuffers() {    squareVertexPositionBuffer = gl.createBuffer();    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    vertices = [         1.0,  1.0,  0.0,        -1.0,  1.0,  0.0,         1.0, -1.0,  0.0,        -1.0, -1.0,  0.0    ];    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);    squareVertexPositionBuffer.itemSize = 3;    squareVertexPositionBuffer.numItems = 4;  }  function onWindowResize( event ) {    canvas.width = window.innerWidth;    canvas.height = window.innerHeight;    gl.viewport( 0, 0, canvas.width, canvas.height );  }    function handleLoadedTexture(texture) {    gl.bindTexture(gl.TEXTURE_2D, texture);    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);    gl.bindTexture(gl.TEXTURE_2D, null);  }   function initTexture() {    neheTexture = gl.createTexture();    neheTexture.image = new Image();    neheTexture.image.onload = function() {      handleLoadedTexture(neheTexture)    }    //neheTexture.image.src = "tex2.jpg";    neheTexture.image.src = "http://www.iquilezles.org/apps/shadertoy/presets/tex3.jpg";   }      function drawScene() {    //gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);    gl.clear(gl.COLOR_BUFFER_BIT);    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);    setUniforms();    gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);  }  function webGLStart_deform() {    canvas = document.getElementById("my-canvas-deform");    initGL(canvas);    initShaders()    initBuffers();    initTexture();    gl.clearColor(0.0, 0.0, 0.0, 1.0);    gl.disable(gl.DEPTH_TEST);    setInterval(drawScene, 16);  }  &lt;/script&gt;&lt;br /&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-fpqxcMvs-Ac/TftkqgonKeI/AAAAAAAAAaI/TXIA6ArIJn4/s1600/deform-interference.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="168" src="http://4.bp.blogspot.com/-fpqxcMvs-Ac/TftkqgonKeI/AAAAAAAAAaI/TXIA6ArIJn4/s200/deform-interference.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;'deform'&amp;nbsp;interference&amp;nbsp;effect&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;This effect is one of my all time favourites. It is somewhat similar to the &lt;a href="http://adrianboeing.blogspot.com/2011/01/xor-demoeffect-in-webgl.html"&gt;XOR bitplasma&lt;/a&gt; effect with which I started the tutorial series based on &lt;a href="http://www.iquilezles.org/apps/shadertoy/"&gt;iq's shader toy&lt;/a&gt;. This effect is an 'interference' of two points based on the subtraction of the radii and angles.&lt;br /&gt;&lt;br /&gt;Jumping straight to the solution; the code we are trying to decipher is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;float a1 = atan(p.y-offset1.y,p.x-offset1.x);&lt;br /&gt;float r1 = sqrt(dot(p-offset1,p-offset1));&lt;br /&gt;float a2 = atan(p.y-offset2.y,p.x-offset2.x);&lt;br /&gt;float r2 = sqrt(dot(p-offset2,p-offset2));&lt;br /&gt;&lt;br /&gt;vec2 uv;&lt;br /&gt;uv.x =(r1-r2);&lt;br /&gt;uv.y =(a1-a2);&lt;/code&gt;&lt;br /&gt;&lt;code&gt; &lt;/code&gt;&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-tYPMfoI_Tdo/TftYaIQcgLI/AAAAAAAAAZE/SLMIz2CSUNM/s1600/r1-3d-z.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="158" src="http://4.bp.blogspot.com/-tYPMfoI_Tdo/TftYaIQcgLI/AAAAAAAAAZE/SLMIz2CSUNM/s200/r1-3d-z.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;r1&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;So why does it look the way it looks?&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-dDR2yvzdI54/TftYkpii9cI/AAAAAAAAAZI/2V_4pYqlL0A/s1600/r2-3d-z.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="161" src="http://3.bp.blogspot.com/-dDR2yvzdI54/TftYkpii9cI/AAAAAAAAAZI/2V_4pYqlL0A/s200/r2-3d-z.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;r2&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Lets start with the radius part. If we just look at one radius (r1) we would expect to see a steadily increasing value radiating out from our offset point (in all my examples this will be at 0.3)&lt;br /&gt;&lt;br /&gt;And this is exactly what we see when we plot this. If we plot the inverse (negative r2, offset to -0.3) we should see the inverse, that is, a steadily decreasing value radiating from the offset point.&lt;br /&gt;&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://4.bp.blogspot.com/-4G4DDv5J4MM/TftY3kjShVI/AAAAAAAAAZM/JxfRB82RiA8/s1600/r1-r2-3d-z.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="264" src="http://4.bp.blogspot.com/-4G4DDv5J4MM/TftY3kjShVI/AAAAAAAAAZM/JxfRB82RiA8/s320/r1-r2-3d-z.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;r1-r2&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-7mXAAzDoKyA/TftY_v1TgCI/AAAAAAAAAZQ/rKBVa9Dphas/s1600/xbyx.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="140" src="http://1.bp.blogspot.com/-7mXAAzDoKyA/TftY_v1TgCI/AAAAAAAAAZQ/rKBVa9Dphas/s200/xbyx.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;So if we combine these (r1-r2) we get a nice smooth surface transition between these two patterns. Where does this blending come from?&lt;br /&gt;&lt;br /&gt;Lets take it back a step and look at our problem in just one dimension. Our definition of the radius is sqrt(x*x+y*y), in 1D we can plot x*x and sqrt(x*x):&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-wwcuUrs6DSI/Tftbklly1vI/AAAAAAAAAZc/vcc24P63Bao/s1600/r1-r2-00.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="150" src="http://4.bp.blogspot.com/-wwcuUrs6DSI/Tftbklly1vI/AAAAAAAAAZc/vcc24P63Bao/s200/r1-r2-00.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Coming back to the generation of the surface, we can plot two interfering 1D functions, that is sqrt((x-0.3)*(x-0.3)) and sqrt((x+0.3)*(x+0.3)), and the difference (i.e. the first subtract the second). This gives us a ramped step between the functions as each reaches its turning point.&lt;br /&gt;&lt;br /&gt;We can see the same feature in the surface, if we view it from an appropriate angle.&lt;br /&gt;&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://4.bp.blogspot.com/-ewxI7VIhEfo/TftbHfGzJbI/AAAAAAAAAZY/TKQTpWTlGQA/s1600/r1-r2-3d-easyview-z.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/-ewxI7VIhEfo/TftbHfGzJbI/AAAAAAAAAZY/TKQTpWTlGQA/s320/r1-r2-3d-easyview-z.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;r1-r2,&amp;nbsp;alternative&amp;nbsp;view&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;a href="http://2.bp.blogspot.com/-TgECKd3BcmA/Tfta_Jh8Y-I/AAAAAAAAAZU/xCoAxfTINm8/s1600/xbyxplusk.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="142" src="http://2.bp.blogspot.com/-TgECKd3BcmA/Tfta_Jh8Y-I/AAAAAAAAAZU/xCoAxfTINm8/s200/xbyxplusk.png" width="200" /&gt;&lt;/a&gt;We still haven't discovered the cause of the smooth blending that gives such a nice visual effect.  When we add a constant (i.e. offset) to the function sqrt(x*x+k), notice how we now have the turning point at sqrt(k) and have a parabola instead. This is effectively evaluating sqrt(x*x+y*y) for some constant y=sqrt(k).&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-idnExdJl78k/TftcZksHSPI/AAAAAAAAAZg/zEnQAX4wwSs/s1600/r1-r2-33.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="150" src="http://4.bp.blogspot.com/-idnExdJl78k/TftcZksHSPI/AAAAAAAAAZg/zEnQAX4wwSs/s200/r1-r2-33.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;So, if we now consider the two extremes, again plotting in 1D but considering the 2D case for both our x-offsets of =-0.3 and 0.3 we get a set of blended curves (dark blue/red is y=-0.3, light blue/purple is y = 0.3).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And that is where our full surface comes from.&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/-4G4DDv5J4MM/TftY3kjShVI/AAAAAAAAAZM/JxfRB82RiA8/s1600/r1-r2-3d-z.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="264" src="http://4.bp.blogspot.com/-4G4DDv5J4MM/TftY3kjShVI/AAAAAAAAAZM/JxfRB82RiA8/s320/r1-r2-3d-z.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;hr /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-nuVMMNqjmaU/Tftf_jsbqDI/AAAAAAAAAZ0/dOugN4zBX5Q/s1600/atanxatan1-y.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="97" src="http://1.bp.blogspot.com/-nuVMMNqjmaU/Tftf_jsbqDI/AAAAAAAAAZ0/dOugN4zBX5Q/s200/atanxatan1-y.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Left: atan(x) Right: atan(1/y)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Now we want to understand the blend in the angles. The generating function is nothing more complex than atan(x/y). Below is a graph of atan(x), followed by atan(1/y). Note: There are different viewing angles for each function so it is easier to see the curvature.&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;br /&gt;&lt;/div&gt;If we combine these two equations into one (i.e. atan(x/y)) we get:&lt;br /&gt;&lt;br /&gt;&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://1.bp.blogspot.com/-z3GKnGk85Dc/TfteXVPpzxI/AAAAAAAAAZw/furq1DhJMOk/s1600/atanxy-z.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="277" src="http://1.bp.blogspot.com/-z3GKnGk85Dc/TfteXVPpzxI/AAAAAAAAAZw/furq1DhJMOk/s320/atanxy-z.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;atan(x/y)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Now, we just need to understand the interference pattern that is generated from two of these functions interacting. I'm going to take a shortcut here and just let an animated gif tell the story. This animation shows a discretized version of the angles (first in steps of ~60 degrees, then ~30, etc.) interacting for the equation a1-a2 from the code snippet.&lt;br /&gt;&lt;br /&gt;&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://1.bp.blogspot.com/-A88ApiDN3Vc/TfthWYWjmVI/AAAAAAAAAZ4/_WBtXTTxobw/s1600/a1-a2-animated-loop.gif" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/-A88ApiDN3Vc/TfthWYWjmVI/AAAAAAAAAZ4/_WBtXTTxobw/s320/a1-a2-animated-loop.gif" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;a1-a2&amp;nbsp;discretized&amp;nbsp;and animated (open as a&amp;nbsp;separate&amp;nbsp;image)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;From the gif you can see how the curves evolve. To understand these better we can take a look at how this curve pattern comes about for a constant difference angle. If we modify the end of our original shader code to:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-AkxF7i3olAY/TftkDqNbqpI/AAAAAAAAAZ8/vE7gj7-3B6s/s1600/deform-curve.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="177" src="http://2.bp.blogspot.com/-AkxF7i3olAY/TftkDqNbqpI/AAAAAAAAAZ8/vE7gj7-3B6s/s200/deform-curve.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;code&gt;&lt;br /&gt;uv.y = (a2-a1);&lt;br /&gt;float k = 0.0;&lt;br /&gt;if ((uv.y &amp;gt; 0.3) &amp;amp;&amp;amp; (uv.y&amp;lt;0.31)) k = 1.0; gl_FragColor = vec4(col.r+k,col.g+k,col.b+k,1.0); &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The resulting image is still the original effect, but one of the curves is highlighted (in white). This represents a curve where (a2-a1) ~= 0.3 &lt;br /&gt;&lt;br /&gt;We can understand this curve by generating a set of triangles in which two vertices are fixed, and the difference between two angles is held constant. By altering one angle the final vertex will generate the sweeping curve in the original image (See &lt;a href="http://en.wikipedia.org/wiki/Law_of_sines"&gt;Law of Sines&lt;/a&gt;). In the example below, we vary a1 and hold a2 as (a1 - 30 degrees).&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/-UrcXsQXLsCA/TftkN6kBF3I/AAAAAAAAAaA/Tt1ym42hu-w/s1600/triangle.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="224" src="http://4.bp.blogspot.com/-UrcXsQXLsCA/TftkN6kBF3I/AAAAAAAAAaA/Tt1ym42hu-w/s320/triangle.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This generates our final explanatory image of the sweeping triangles:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-EraTlszzeAg/TftkVflD0SI/AAAAAAAAAaE/pui1-ZrlvK8/s1600/triangle-curve-z.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="176" src="http://2.bp.blogspot.com/-EraTlszzeAg/TftkVflD0SI/AAAAAAAAAaE/pui1-ZrlvK8/s320/triangle-curve-z.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Finally! The full effect has been deciphered, click the button below to see it in action. (You will need a WebGL enabled browser)&lt;br /&gt;&lt;br /&gt;&lt;form&gt;&lt;input onclick="webGLStart_deform()" type="button" value="Click me!" /&gt; &lt;/form&gt;&lt;canvas height="300" id="my-canvas-deform" width="400"&gt; Your browser doesn't appear to support the HTML5 &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element. &lt;/canvas&gt;&lt;br /&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/17188375-778239073989261086?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/778239073989261086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=778239073989261086' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/778239073989261086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/778239073989261086'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/06/deform-textured-interference-effect-in.html' title='Deform (textured interference) effect in WebGL'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-fpqxcMvs-Ac/TftkqgonKeI/AAAAAAAAAaI/TXIA6ArIJn4/s72-c/deform-interference.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-5892345688339412077</id><published>2011-06-13T23:08:00.002+08:00</published><updated>2011-06-13T23:20:50.706+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><title type='text'>Demoparties</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-fd_qC_knXA0/TfYhGyu9CEI/AAAAAAAAAYg/u6HoxQtmxNA/s1600/demoparty_logo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="170" src="http://2.bp.blogspot.com/-fd_qC_knXA0/TfYhGyu9CEI/AAAAAAAAAYg/u6HoxQtmxNA/s200/demoparty_logo.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;Australia is hosting another demo party, this time in Sydney called &lt;a href="http://www.defame.com.au/flashback.php"&gt;Flashback 2011&lt;/a&gt;. It will be interesting to see what gets released. &lt;br /&gt;&lt;br /&gt;For a more international focus there is the &lt;a href="http://mozillalabs.com/demoparty"&gt;Mozilla Demoparty&lt;/a&gt; with WebGL, CSS, GIF animation, and Audio competitions. The 'event' started on the 10th of June, and submissions close on the 30th of July. Take a look at the original &lt;a href="http://mozillalabs.com/blog/2011/05/demoparty-in-your-town/"&gt; announcement of the Mozilla Demoparty&lt;/a&gt; incase you want to organize a local contributing event.&lt;br /&gt;&lt;br /&gt;If your looking for a modern tracker to make your audio you can try the &lt;a href="http://schismtracker.org/wiki/Schism%20Tracker"&gt;open source Schism Tracker (Impulse Tracker clone)&lt;/a&gt;. (Daniel Gagan has a nice blog post on various methods for &lt;a href="http://forestmist.org/2010/04/html5-audio-loops/"&gt;implementing HTML5 audio loops&lt;/a&gt;) For your WebGL needs, there are a number of libraries/engines to try:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.ambiera.com/copperlicht/index.html"&gt;CopperLicht&lt;/a&gt; a port of the Irrlicht 3D engine to WebGL&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.x3dom.org/?page_id=5"&gt;X3D via WebGL&lt;/a&gt; an easy way to display 3D models&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.glge.org/about/"&gt;GLGE&lt;/a&gt; a WebGL javascript library with some basic 3D engine functions (Keyframe animation, Lighting &amp;amp; Materials, etc)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://github.com/mrdoob/three.js/"&gt;three.js&lt;/a&gt; a lightweight 3d Javascript engine&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/o3d/"&gt;o3d WebGL port&lt;/a&gt;, from google. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://blog.jaxgl.com/what-is-jax/"&gt;JAX framework&lt;/a&gt;.&lt;br /&gt;&lt;/ul&gt;Should be enough to get you started. Of related interest is a description of &lt;a href="http://blog.tojicode.com/2011/05/rage-webgl-tech-talk.html"&gt;Brandan Jones' WebGL renderer for id's Rage levels&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/17188375-5892345688339412077?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/5892345688339412077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=5892345688339412077' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5892345688339412077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5892345688339412077'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/06/demoparties.html' title='Demoparties'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-fd_qC_knXA0/TfYhGyu9CEI/AAAAAAAAAYg/u6HoxQtmxNA/s72-c/demoparty_logo.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-6355812758171157557</id><published>2011-06-05T18:27:00.000+08:00</published><updated>2011-06-05T18:27:55.847+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><category scheme='http://www.blogger.com/atom/ns#' term='fluid'/><title type='text'>Catchup Post: Robotics and Physical Simulations</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-SxS2B630Lx0/TetZ-lRzNRI/AAAAAAAAAYc/L0FHCOGGqQk/s1600/TLDtracker.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/-SxS2B630Lx0/TetZ-lRzNRI/AAAAAAAAAYc/L0FHCOGGqQk/s200/TLDtracker.png" width="196" /&gt;&lt;/a&gt;&lt;/div&gt;A number of robotics related bits of interest from the last few months:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.cc.gatech.edu/~jtan34/project/articulatedSwimmingCreatures.html"&gt;Articulated Swimming Creatures&lt;/a&gt; by Jie Tan et. al actually performed work I had planned for my thesis, but never did complete. They simulated various creatures using different fluid simulation methods, and found they get different results. This was the same thing I found, and generalised via &lt;a href="http://pal.sf.net/"&gt;PAL&lt;/a&gt; and used to generate control algorithms that can transfer to the real world for an underwater vehicle.  &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=1GhNXHCQGsM"&gt;Predator: A Visual Tracker that Learns from its Errors&lt;/a&gt; by Zdenek Kalal went viral. I think it was a bit hyped (thanks to a clever name), but the TLD algorithm is interesting, and there are some worthwhile items to note. First of all it is &lt;a href="https://github.com/zk00006/OpenTLD"&gt;an open source visual tracker&lt;/a&gt;, and that there is a freely available&lt;br /&gt;&lt;a href="http://www.youtube.com/user/GoogleTechTalks#p/u/7/lmG_FjG4Dy8"&gt;Google Tech Talk on TLD&lt;/a&gt;. In essence, Zdenek asserts that a tracker based on similarity of image patches will always lose its target and demonstrates trackers with learnt models from image data perform very well. (Similar to how &lt;a href="http://www.opentl.org/"&gt;models improve tracking in OpenTL&lt;/a&gt;). Zdenek et al. describe a way to generate more test sets using two experts (positive - objects must remain nearby, negative - only one true location per frame) and leverages &lt;a href="http://adrianboeing.blogspot.com/2009/03/adaboost.html"&gt;boosting&lt;/a&gt; to get results. The total flow of operations are then: 1. Tracking and prediction, 2. Expert systems plus Detection, into Learning. 3. Re-Detection, using learnings.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.wildbunny.co.uk/blog/2011/04/06/physics-engines-for-dummies/"&gt;Paul Firth published a great introductory article on Physics Engines&lt;/a&gt;. Very handy. While your at it, &lt;a href="http://altdevblogaday.org/2011/05/29/points-vertices-and-vectors/"&gt;Wolfgang Engel did a great post on some maths basics&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://sourceforge.net/projects/hacd/"&gt;Hierarchical Approximate Convex Decomposition of 3D Meshes (HACD)&lt;/a&gt; (&lt;a href="ftp://ftp.elet.polimi.it/users/Stefano.Tubaro/ICIP_USB_Proceedings_v2/pdfs/0003501.pdf"&gt;HACD paper&lt;/a&gt;) is a method for representing objects as compound convex hulls (speeds up collision detection), that seems to outperform any other method I have seen. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://graphics.ewha.ac.kr/C2A/"&gt;C2A by Min Tang&lt;/a&gt; et. al is a method for speeding up continuous collision detection with conservative advancement. A good paper, and source code is available.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://sourceforge.net/projects/pappe/"&gt;PAPPE is a Pascal Physics Engine&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://graphics.ethz.ch/publications/papers/papers.php"&gt;Barbara Solenthaler and Markus Gross&lt;/a&gt; published work on Two-Scale SPH Particle Simulation, an obvious idea (speedup simulations by mixing level of detail for SPH, they get about 2.2x speedups), someone had to do it. The videos are interesting nevertheless.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;On the topic of SPH, &lt;a href="http://physxinfo.com/news/5759/physx-research-eulerian-water-simulation-and-solids-through-oriented-particles/"&gt;PhysXinfo has an article on the latests nVidia PhysX/Novodex/ETH research&lt;/a&gt; on fluid systems, of particular interest is Solid Simulation with Oriented Particles. Another interesting post is by &lt;a href="https://mmack.wordpress.com/2010/11/01/adventures-in-fluid-simulation/"&gt;Miles Macklin on fluid simulations&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://software.intel.com/en-us/articles/colony/"&gt;Intel released 'Colony' a crowd-simulation system&lt;/a&gt;, comes with source code.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.dcs.gla.ac.uk/~girolami/Machine_Learning_Module_2006/"&gt;Lectures on machine learning with Matlab&lt;/a&gt;. Covers SVM, NN, EM, Bayesian methods, and image analysis. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://github.com/aichallenge/aichallenge/wiki"&gt;Ant colony optimization will be the next google AI challenge&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.ros.org/wiki/urdf"&gt;An XML Unified Robot Description Format (URDF)&lt;/a&gt;, again, like many other formats before it it has inherit limitations. COLLADA 1.5 Kinematics (library_kinematics_models) is probably a better choice.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;On the topic of XML, and other data interchange formats &lt;a href="http://jsoncpp.sourceforge.net/"&gt;JSON cpp&lt;/a&gt; is a C++ library to handle exchanging JSON data.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.araa.asn.au/acra/"&gt;ACRA, the Australasian Conference on Robotics and Automation&lt;/a&gt; will take place in December in Melbourne.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;And just incase you've been hiding under a rock for the last while, the next big DARPA competition is the &lt;a href="http://spectrum.ieee.org/automaton/robotics/robotics-software/darpa-arm-program?utm_source=feedburner&amp;amp;utm_medium=feed&amp;amp;utm_campaign=Feed%3A+IeeeSpectrum+%28IEEE+Spectrum%29"&gt;ARM manipulation program&lt;/a&gt;. Lots of interesting results are coming out of that project, but thats for another time.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Finally Heat-1 the space rocket build by danish amateurs &lt;a href="http://www.copenhagensuborbitals.com/"&gt;Copenhagen Suborbitals&lt;/a&gt; successfully launched. (&lt;a href="http://www.youtube.com/watch?v=ua9oGxNNGd0"&gt;TED talk here&lt;/a&gt;). See the video below. &lt;iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/GmGmymAWI4E" width="425"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-6355812758171157557?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/6355812758171157557/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=6355812758171157557' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6355812758171157557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6355812758171157557'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/06/catchup-post-robotics-and-physical.html' title='Catchup Post: Robotics and Physical Simulations'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-SxS2B630Lx0/TetZ-lRzNRI/AAAAAAAAAYc/L0FHCOGGqQk/s72-c/TLDtracker.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-1570573677685214700</id><published>2011-05-16T21:41:00.003+08:00</published><updated>2011-05-25T22:24:26.622+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='education'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><title type='text'>Slides on the Demoscene and WebGL demo effects</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-GDnyuZKw8LE/Td0Q4W3vN4I/AAAAAAAAAYY/Yo8dI0wm-7A/s1600/webgl-demoscene.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="157" src="http://4.bp.blogspot.com/-GDnyuZKw8LE/Td0Q4W3vN4I/AAAAAAAAAYY/Yo8dI0wm-7A/s200/webgl-demoscene.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;I gave a guest lecture at &lt;a href="http://www.ecu.edu.au/"&gt;ECU&lt;/a&gt; for the Advanced 3D Graphics programming class. The slides cover:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A bit about me&lt;br /&gt;&lt;/li&gt;&lt;li&gt;An introduction to the &lt;a href="http://scene.org/"&gt;Demoscene&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;An introduction to &lt;a href="http://get.webgl.org/"&gt;WebGL&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;WebGL Shaders&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Screen space&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Sine/Cosine Plasma effect&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Circle equation and &lt;a href="http://adrianboeing.blogspot.com/2011/01/xor-demoeffect-in-webgl.html"&gt;XOR Bitplasma effect&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Tangent function, 3d to 2d projection, Texture mapping and &lt;a href="http://adrianboeing.blogspot.com/2011/01/webgl-tunnel-effect-explained.html"&gt;Tunnel effect&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://adrianboeing.blogspot.com/2011/01/twist-effect-in-webgl.html"&gt;Twist effect&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Julia fractal&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;You can get the &lt;a href="http://www.adrianboeing.com/files/webgl-demoscene.pdf"&gt;slides on WebGL and the Demoscene here.&lt;/a&gt; Enjoy!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-1570573677685214700?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/1570573677685214700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=1570573677685214700' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/1570573677685214700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/1570573677685214700'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/05/slides-on-demoscene-and-webgl-demo.html' title='Slides on the Demoscene and WebGL demo effects'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-GDnyuZKw8LE/Td0Q4W3vN4I/AAAAAAAAAYY/Yo8dI0wm-7A/s72-c/webgl-demoscene.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-6799516939061137290</id><published>2011-05-09T21:18:00.040+08:00</published><updated>2011-05-25T21:32:42.016+08:00</updated><title type='text'>China Holiday</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-5le7LNelLnc/Td0DkgZz8AI/AAAAAAAAAYI/lw7HIbEV9SI/s1600/yangshuo-small.JPG" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="149" src="http://4.bp.blogspot.com/-5le7LNelLnc/Td0DkgZz8AI/AAAAAAAAAYI/lw7HIbEV9SI/s200/yangshuo-small.JPG" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Yangshuo&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;I have been holidaying in china, which explains the lack of posts on the blog.&lt;br /&gt;&lt;br /&gt;I went to China as a relatively experienced independent traveler with a western-cultural-view of China. A few things stood out to me as being quite different to the current prevailing western perception of China:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;China isn't one unified country. China is only slightly smaller than the US, and 1.24x the size of Australia - plenty of room for variance. There are regions of conflict (e.g. Tibet, Xinjiang Uighur, etc.) and there is a massive diversity in the people, cultures, and languages. 'One country, two systems' (e.g. Hong Kong) gives a bit of an indication of the diversity within China. I'm not sure there is another country with this range of diversity.&lt;br /&gt;&lt;/li&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-dR4ciuorgZY/Td0D_ISBjLI/AAAAAAAAAYU/abdC8vARENM/s1600/yangshou-shangrila-small.JPG" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="149" src="http://3.bp.blogspot.com/-dR4ciuorgZY/Td0D_ISBjLI/AAAAAAAAAYU/abdC8vARENM/s200/yangshou-shangrila-small.JPG" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Shangri-La&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;li&gt;There are plenty of rich people in China (According to some (dubious) sources, there are more billionaires in China than the US. In any case, there are plenty of Starbucks, McDonalds and KFC restaurants!). Especially in cities like Beijing and Shanghai. China's GDP and PPP have increased significantly in recent years, and in urban areas people are much better off than the western perception which is based on historical figures. There are obviously still a great number of poor people too.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I found the level of censorship is not as great as western sources report. It seems to be a 'work in progress', but people appear to have a fair amount of freedom of expression (compared to the perception presented by western media on communist nations). There were people on Chinese TV openly complaining about government corruption, housing problems, etc.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-zoPafF69eKQ/Td0DtxCGlGI/AAAAAAAAAYM/b-R7UwVJoNY/s1600/templeheaven-small.JPG" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="149" src="http://4.bp.blogspot.com/-zoPafF69eKQ/Td0DtxCGlGI/AAAAAAAAAYM/b-R7UwVJoNY/s200/templeheaven-small.JPG" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Temple of Heaven&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Some travel tips for an independent traveler: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;China changes rapidly. Take an up to date travel guide.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Booking flights, accommodation, etc. can be quite difficult. &lt;a href="http://www.ctrip.com/"&gt;Ctrip&lt;/a&gt; is a very helpful website.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Take a print out of your accommodations address in mandarin, phone number, and a map. This will increase the probability of you arriving at your destination.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Avoid getting scammed with travel bookings by asking any decent hotel to help in booking anything from tours to transport to taxis. You will always pay a surcharge, but never get ripped off.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;There can be a large cultural barrier. I've traveled to countries with significant language barriers, but have always been able to explain myself via gestures and drawing pictures. I guess the cultural barrier made it difficult to explain myself!&lt;br /&gt;&lt;/li&gt;&lt;li&gt;When asking for directions ask multiple people. Often someone who doesn't know will just make something up.&lt;br /&gt;&lt;/li&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-9t-QDoFo720/Td0D2P5RBDI/AAAAAAAAAYQ/KyaCjG9bSOA/s1600/greatwall-small.JPG" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/-9t-QDoFo720/Td0D2P5RBDI/AAAAAAAAAYQ/KyaCjG9bSOA/s200/greatwall-small.JPG" width="149" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Great Wall&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;li&gt;Be careful when haggling, often the "pay half" rule doesn't apply, and "pay 1/10th" is more appropriate.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;There is a lot of internal tourism in China. Don't expect to see many foreigners. Expect to draw a fair bit of attention from the locals.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Take a print-out of a few key phrases in mandarin. I found this particularly helpful in deciphering menus and ordering food.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Highlights for me were the Temple of heaven and Summer palace in Beijing, the Putuo Zongcheng Temple in Chengde, the Great Wall surroundings, Shangri La, Hong Kong and Yangshuo.&lt;br /&gt;&lt;br /&gt;Expect a return to technical topics soon!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-6799516939061137290?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/6799516939061137290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=6799516939061137290' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6799516939061137290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6799516939061137290'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/05/china-holiday.html' title='China Holiday'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-5le7LNelLnc/Td0DkgZz8AI/AAAAAAAAAYI/lw7HIbEV9SI/s72-c/yangshuo-small.JPG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-2749635288676061327</id><published>2011-03-31T23:55:00.000+08:00</published><updated>2011-03-31T23:55:42.511+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='compilers'/><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='education'/><category scheme='http://www.blogger.com/atom/ns#' term='raytracing'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><title type='text'>March update</title><content type='html'>I didn't want to have a month without a post, so here are some links for the month:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.gdconf.com/"&gt;GDC&lt;/a&gt; 2011 is over again. I'll do a breakdown soon, but meanwhile take a look yourself at &lt;a href="http://publications.dice.se/"&gt;DICE publications on Battlefield 3&lt;/a&gt;, &lt;a href="http://www.nvidia.com/object/gdc2011.html"&gt;nVidia's GDC publications&lt;/a&gt;, &lt;a href="http://developer.amd.com/documentation/presentations/Pages/default.aspx#GDC"&gt; AMD GDC&lt;/a&gt; and ofcourse the &lt;a href="http://www.gdcvault.com/free/gdc-11"&gt;official GDC vault (free)&lt;/a&gt;. (Maciej Sinilo has a nice collection &lt;a href="http://msinilo.pl/blog/?p=724"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Game-Physics-Pearls-Gino-Bergen/dp/1568814747?tag=realtimerenderin"&gt;Game Physics Pearls&lt;/a&gt; has been published by Gino van den Bergen and Dirk Gregorius. Dirk is a very knowledgeable guy, and Gino wrote &lt;a href="http://www.dtecta.com/"&gt;SOLID&lt;/a&gt;, so I'm sure it's great.&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.sciencebooksonline.info/computer-science.html"&gt;ScienceBooksOnline&lt;/a&gt; has a collection of free books.&lt;br /&gt;&lt;li&gt;Paul Firth has a &lt;a href="http://www.wildbunny.co.uk/blog/2011/03/25/speculative-contacts-an-continuous-collision-engine-approach-part-1/"&gt;great interactive blog post on contact resolution&lt;/a&gt;, and introduces a method used in &lt;i&gt;Little Big Planet&lt;/i&gt; he calls "Speculative Contacts".&lt;br /&gt;&lt;li&gt;PhysX info has a &lt;a href="http://physxinfo.com/articles/?page_id=389"&gt;comparison of different clothing simulation systems&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;&lt;a href="http://glm.g-truc.net/"&gt;GLM&lt;/a&gt; is an OpenGL syntax math library.&lt;br /&gt;&lt;li&gt;&lt;a href="http://cairographics.org/"&gt;Cairo&lt;/a&gt; is a 2D graphics library that supports both OpenGL and PDF output.&lt;br /&gt;&lt;li&gt;&lt;a href="http://people.mozilla.org/~bjacob/iap2011/slides/#slide1"&gt;An MIT WebGL tutorial&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;&lt;a href="http://blog.lostdecadegames.com/how-to-embed-html5-into-a-native-mac-osx-app"&gt;How to convert your HTML5 page into a native OSX app&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;Paul Grenfell added another small &lt;a href="http://www.evilpaul.org/wp/?p=318"&gt;raycasting OpenProcessing demo&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;&lt;a href="http://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/"&gt;Photoshop filters implemented in GLSL&lt;/a&gt;&lt;br /&gt;&lt;li&gt;Herwig Hauser has an amazing &lt;a href="http://homepage.univie.ac.at/herwig.hauser/bildergalerie/gallery.html"&gt;gallery of 3D algebraic surfaces&lt;/a&gt; - useful for 4k productions.&lt;br /&gt;&lt;li&gt;On that topic, Auld has a great snippet on &lt;a href="http://sizecoding.blogspot.com/2008/12/code-for-moving-camera-in-glsl.html"&gt;miniature GLSL code for moving a camera&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;&lt;a href="http://wildfiregames.com/0ad/"&gt;0 AD&lt;/a&gt; is an open source 'Age of Empires' style game.&lt;br /&gt;&lt;li&gt;&lt;a href="http://ninite.com/"&gt;Ninite&lt;/a&gt; is like apt-get for Windows. (Installation package manager)&lt;br /&gt;&lt;li&gt;&lt;a href="http://graphics.berkeley.edu/papers/Held-UBA-2010-03/"&gt;A siggraph paper on the miniature effect&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://phototour.cs.washington.edu/bundler/"&gt;Bundler&lt;/a&gt; is an open source tool to generate structure from motion from unordered images. (It was published in 2006, but now you can look at the code)&lt;br /&gt;&lt;li&gt;&lt;a href="http://gpgpu.org/2011/02/08/gpu-ocelot-2-0-released"&gt;GPU Ocelot 2.0&lt;/a&gt; supports AMD devices now. CUDA for AMD.&lt;br /&gt;&lt;li&gt;Microsoft's paper on the &lt;a href="http://research.microsoft.com/pubs/145347/BodyPartRecognition.pdf"&gt;Kinect bodypart tracking algorithm&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;Looking for a place to publish? &lt;a href="http://www.wikicfp.com/cfp/home"&gt;Wiki Call for Papers&lt;/a&gt; collects conference paper submission deadlines and more. (Neat!)&lt;br /&gt;&lt;/ul&gt;The pick of the month has to be the &lt;a href="http://www.i-programmer.info/news/91-hardware/2183-is-it-a-bird-no-its-a-robot.html"&gt;new Festo production, the SmartBird ornithopter&lt;/a&gt;. &lt;a href="http://www.festo.com/cms/en_corp/11369.htm"&gt;(Official site has a PDF spec-sheet)&lt;/a&gt;. Video below:&lt;iframe title="YouTube video player" width="560" height="349" src="http://www.youtube.com/embed/nnR8fDW3Ilo?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-2749635288676061327?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/2749635288676061327/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=2749635288676061327' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/2749635288676061327'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/2749635288676061327'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/03/march-update.html' title='March update'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/nnR8fDW3Ilo/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-632404466496040106</id><published>2011-02-24T23:50:00.000+08:00</published><updated>2011-02-24T23:50:29.126+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='magic2010'/><title type='text'>WAMBot on ABC Catalyst</title><content type='html'>&lt;a href="http://www.abc.net.au/catalyst/default.htm"&gt;ABC Catalyst&lt;/a&gt; did a segment on the &lt;a href="http://en.wikipedia.org/wiki/Multi_Autonomous_Ground-robotic_International_Challenge"&gt;MAGIC 2010 competition&lt;/a&gt;, you can watch the &lt;a href="http://www.abc.net.au/catalyst/stories/3147573.htm"&gt;Catalyst RobotWars MAGIC2010 segment on their website&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;A more in-depth explanation of the problems we faced: The robots were stored overnight on site in a tent, and unfortunately the next day a lot of moisture had gathered in the electronics. Since we had used cheap GPS units, a number of them then failed on the day. The software we had written was not robust enough to cope with the faulty units and so the robots would think they were in an incorrect location. As the fleet of robots could not agree on their locations the map data was incomplete, and subsequently the robots were difficult to navigate. &lt;br /&gt;&lt;br /&gt;Other software bugs, short battery life and communications drops also hindered the performance.&lt;br /&gt;&lt;br /&gt;Next time: More testing, and focus on robustness and fallback options, and buy equipment with an IP rating of 32 or more.&lt;br /&gt;&lt;br /&gt;A short clip of the interview is on youtube:&lt;br /&gt;&lt;iframe title="YouTube video player" width="560" height="349" src="http://www.youtube.com/embed/n3PDuRAvXdk?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-632404466496040106?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/632404466496040106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=632404466496040106' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/632404466496040106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/632404466496040106'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/02/wambot-on-abc-catalyst.html' title='WAMBot on ABC Catalyst'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/n3PDuRAvXdk/default.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-575900060666860786</id><published>2011-02-20T21:07:00.000+08:00</published><updated>2011-02-20T21:07:51.078+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><title type='text'>Newton Physics Engine</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;a href="http://3.bp.blogspot.com/-mfuDyEzcvHU/TWERjv0IV7I/AAAAAAAAAX8/pIjP4qIEvM0/s1600/newton-dynamics-logo.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-mfuDyEzcvHU/TWERjv0IV7I/AAAAAAAAAX8/pIjP4qIEvM0/s1600/newton-dynamics-logo.jpg" /&gt;&lt;/a&gt;In an unexpected move the &lt;a href="http://newtondynamics.com/"&gt;Newton Physics Engine&lt;/a&gt; has been &lt;a href="http://code.google.com/p/newton-dynamics/"&gt;open sourced with the zlib licence&lt;/a&gt;. I haven't been following this engines developments closely since the 1.x versions. Julio has released the &lt;a href="https://newton-dynamics.googlecode.com/svn/trunk"&gt;3.0 version over svn&lt;/a&gt; as well.&lt;br /&gt;&lt;br /&gt;Finally, a chance to figure out some of Newton's strange behaviour I noticed in the &lt;a href="http://pal.sf.net/"&gt;PAL&lt;/a&gt; physics engine benchmarks.&lt;br /&gt;&lt;br /&gt;&lt;iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/IhOKGBd-7iw?rel=0" title="YouTube video player" width="425"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-575900060666860786?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/575900060666860786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=575900060666860786' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/575900060666860786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/575900060666860786'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/02/newton-physics-engine.html' title='Newton Physics Engine'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-mfuDyEzcvHU/TWERjv0IV7I/AAAAAAAAAX8/pIjP4qIEvM0/s72-c/newton-dynamics-logo.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-7030968917877888588</id><published>2011-02-12T20:19:00.001+08:00</published><updated>2011-06-17T22:38:04.405+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><title type='text'>Sphere effect in WebGL</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;script id="shader-vs" type="x-shader/x-vertex"&gt;//===================================================================================//Vertex Shader//===================================================================================  attribute vec3 aVertexPosition;  void main(void) {    gl_Position = vec4(aVertexPosition, 1.0);  }&lt;/script&gt;&lt;br /&gt;&lt;script id="shader-fs-sphere" type="x-shader/x-fragment"&gt;//Script by Adrian Boeing//www.adrianboeing.com#ifdef GL_ESprecision highp float;#endifuniform float time;uniform vec2 resolution;uniform sampler2D tex;void main(void){vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;vec2 uv;float r = sqrt(dot(p,p));float f =(3.0-sqrt(4.0-5.0*r*r))/(r*r+1.0);uv.x = p.x*f;uv.y = p.y*f;uv.x += 1.5*sin(time);uv.y += cos(time*0.5);float w = 1.7*(p.x+p.y+r*r-(p.x+p.y-1.0)*sqrt(4.0-5.0*r*r)/3.0)/(r*r+1.0);vec3 col =  texture2D(tex,uv).xyz;gl_FragColor = vec4(col*w,1.0);}&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;//===================================================================================//Javascript code for setting up WebGL//===================================================================================  var canvas;  var startTime;   var gl;  var squareVertexPositionBuffer;  var shaderProgram;  var neheTexture;  function initGL(canvas) {    try {      gl = canvas.getContext("experimental-webgl");      gl.viewportWidth = canvas.width;      gl.viewportHeight = canvas.height;    } catch(e) {    }    if (!gl) {      alert("Could not initialise WebGL!");    }    startTime = (new Date()).getTime();  }  function getShader(gl, id) {    var shaderScript = document.getElementById(id);    if (!shaderScript) {      return null;    }    var str = "";    var k = shaderScript.firstChild;    while (k) {      if (k.nodeType == 3) {        str += k.textContent;      }      k = k.nextSibling;    }    var shader;    if (shaderScript.type == "x-shader/x-fragment") {      shader = gl.createShader(gl.FRAGMENT_SHADER);    } else if (shaderScript.type == "x-shader/x-vertex") {      shader = gl.createShader(gl.VERTEX_SHADER);    } else {      return null;    }    gl.shaderSource(shader, str);    gl.compileShader(shader);    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {      alert(gl.getShaderInfoLog(shader));      return null;    }    return shader;  }  function initShaders_sphere() {    var fragmentShader = getShader(gl, "shader-fs-sphere");    //var fragmentShader = getShader(gl, "simple-fs");    var vertexShader = getShader(gl, "shader-vs");    shaderProgram = gl.createProgram();    gl.attachShader(shaderProgram, vertexShader);    gl.attachShader(shaderProgram, fragmentShader);    gl.linkProgram(shaderProgram);    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {      alert("Could not initialise shaders");    }    gl.useProgram(shaderProgram);    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);    shaderProgram.pResolutionUniform = gl.getUniformLocation(shaderProgram, "resolution");    shaderProgram.pTimeUniform = gl.getUniformLocation(shaderProgram, "time");  }  function setUniforms_sphere() {     gl.activeTexture(gl.TEXTURE0);    gl.bindTexture(gl.TEXTURE_2D, neheTexture);    gl.uniform1i(shaderProgram.samplerUniform, 0);      gl.uniform2f(shaderProgram.pResolutionUniform, canvas.width, canvas.height);    var time = (new Date()).getTime();    gl.uniform1f(shaderProgram.pTimeUniform, (time - startTime) / 1000.0);  }  function initBuffers() {    squareVertexPositionBuffer = gl.createBuffer();    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    vertices = [         1.0,  1.0,  0.0,        -1.0,  1.0,  0.0,         1.0, -1.0,  0.0,        -1.0, -1.0,  0.0    ];    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);    squareVertexPositionBuffer.itemSize = 3;    squareVertexPositionBuffer.numItems = 4;  }  function onWindowResize( event ) {    canvas.width = window.innerWidth;    canvas.height = window.innerHeight;    gl.viewport( 0, 0, canvas.width, canvas.height );  }    function handleLoadedTexture(texture) {    gl.bindTexture(gl.TEXTURE_2D, texture);    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);    gl.bindTexture(gl.TEXTURE_2D, null);  }   function initTexture() {    neheTexture = gl.createTexture();    neheTexture.image = new Image();    neheTexture.image.onload = function() {      handleLoadedTexture(neheTexture)    }    neheTexture.image.src = "http://www.iquilezles.org/apps/shadertoy/presets/tex3.jpg";   }      function drawScene() {    //gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);    gl.clear(gl.COLOR_BUFFER_BIT);    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);    setUniforms_sphere();    gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);  }  function webGLStart_sphere() {    canvas = document.getElementById("my-canvas-sphere");    initGL(canvas);    initShaders_sphere()    initBuffers();    initTexture();    gl.clearColor(0.0, 0.0, 0.0, 1.0);    gl.disable(gl.DEPTH_TEST);    setInterval(drawScene, 16);  }  &lt;/script&gt;&lt;br /&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;This effect is quit interesting to decompose. There are a few versions out there with some confusing formulations and constants, however in essence they all come from the same principles. This version is based on one by &lt;a href="http://www.openprocessing.org/visuals/?visualID=3624"&gt;Luis Gonzalez&lt;/a&gt;, which in turn was based &lt;a href="http://iquilezles.untergrund.net/www/material/deform/pd.zip"&gt;Iñigo Quilez's version (formula 14)&lt;/a&gt;. (iq emailed me to tell me about his windows-only program, but the data file is plain-text - lots more effects to decompose! Thanks iq!)&lt;br /&gt;&lt;br /&gt;First, we start with our &lt;a href="http://adrianboeing.blogspot.com/2011/01/xor-demoeffect-in-webgl.html"&gt;trusty radius calculation&lt;/a&gt;:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;&lt;br /&gt;float r =sqrt(dot(p,p));&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-o4h69zbOLfk/TVPwwYOTfaI/AAAAAAAAAXo/ehMvg2QmwJc/s1600/sphereoutline.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="146" src="http://4.bp.blogspot.com/-o4h69zbOLfk/TVPwwYOTfaI/AAAAAAAAAXo/ehMvg2QmwJc/s200/sphereoutline.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Now to generate a sphere-like looking object we want to create something that looks somewhat like a &lt;a href="http://en.wikipedia.org/wiki/Parabola%22"&gt;parabola&lt;/a&gt; when we take a slice of it. By careful choice of our equations we should be able to construct the appropriate curve. First, since we are creating a sphere we need to create the outline of the sphere, which of course will be a circle. We can use the fact that the &lt;a href="http://en.wikipedia.org/wiki/Square_root#Square_roots_of_negative_and_complex_numbers"&gt;square-root of a negative number will be 'undefined' (complex)&lt;/a&gt; to generate the outline of our sphere:&lt;br /&gt;&lt;br /&gt;&lt;code&gt; float f = sqrt(1.0 - r*r);&lt;br /&gt;gl_FragColor = vec4(f,0.0,0.0, 1.0);&lt;br /&gt;&lt;/code&gt; &lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-C_MaHBVjRjk/TVZzbWeqWpI/AAAAAAAAAX0/j_oWuacZWLg/s1600/innersphere.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="147" src="http://2.bp.blogspot.com/-C_MaHBVjRjk/TVZzbWeqWpI/AAAAAAAAAX0/j_oWuacZWLg/s200/innersphere.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Inside the 'sphere' (inverted below)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;This generates a circle from a re-arrangment of the circle equation (simplified for unit circle):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;x²+y²=1&lt;br /&gt;y²=1-x²&lt;br /&gt;y=sqrt(1-x²)&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;If you apply a linear texture to this, you will notice that it seems like we are looking at the 'inside' of a parabola, and to get something that looks like a sphere, we need to be looking from the 'outside'. We can fix this by inverting our previous result:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;a href="http://4.bp.blogspot.com/-UqGuHUq0ic8/TVPw7XMcy4I/AAAAAAAAAXs/tlfqXSUt0rM/s1600/parabolasphere.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="155" src="http://4.bp.blogspot.com/-UqGuHUq0ic8/TVPw7XMcy4I/AAAAAAAAAXs/tlfqXSUt0rM/s200/parabolasphere.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;code&gt; vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;&lt;br /&gt;vec2 uv;&lt;br /&gt;float r =sqrt(dot(p,p));&lt;br /&gt;float f = 1.0 - sqrt(1.0 - r*r);&lt;br /&gt;uv.x = p.x*f;&lt;br /&gt;uv.y = p.y*f;&lt;br /&gt;gl_FragColor = vec4(texture2D(tex,uv).xyz, 1.0);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Gee, that looks vaguely sphereoid already. We just need to make it look more 3D. Well, lets try generating a sphere from the equation of a circle:&lt;br /&gt;&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-MwuGhMa7Xfk/TVPxDiYT2aI/AAAAAAAAAXw/vhG0FiQgJXU/s1600/sphere.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="160" src="http://1.bp.blogspot.com/-MwuGhMa7Xfk/TVPxDiYT2aI/AAAAAAAAAXw/vhG0FiQgJXU/s200/sphere.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;z=r*r&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;pre&gt;r = sqrt(x*x+y*y);&lt;br /&gt;z = r*r;&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://adrianboeing.blogspot.com/2011/01/webgl-tunnel-effect-explained.html"&gt;Recall from the tunnel tutorial&lt;/a&gt; that to &lt;a href="http://en.wikipedia.org/wiki/3D_projection"&gt;project from 3D to 2D&lt;/a&gt; we simply need to divide by z. We can use the 3D equation of the sphere to calculate the Z depth of the sphere, (i.e. divide by r*r).&lt;br /&gt;&lt;br /&gt;Its starting to look good, now we just need to finish it off with a perspective divide and we have our final result (we can also factor out the redundant square-root):&lt;br /&gt;&lt;br /&gt;&lt;code&gt; vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;&lt;br /&gt;vec2 uv;&lt;br /&gt;float r = dot(p,p);&lt;br /&gt;float f = (1.0-sqrt(1.0-r))/(r);&lt;br /&gt;uv.x = p.x*f + time;&lt;br /&gt;uv.y = p.y*f + time;&lt;br /&gt;gl_FragColor = vec4(texture2D(tex,uv).xyz, 1.0);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;It's not raytracing, but it looks pretty good.&lt;/div&gt;&lt;form&gt;&lt;input onclick="webGLStart_sphere()" type="button" value="Click me!" /&gt; &lt;/form&gt;&lt;canvas height="300" id="my-canvas-sphere" width="400"&gt; Your browser doesn't appear to support the HTML5 &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element. &lt;/canvas&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-7030968917877888588?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/7030968917877888588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=7030968917877888588' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7030968917877888588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7030968917877888588'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/02/sphere-effect-in-webgl.html' title='Sphere effect in WebGL'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-o4h69zbOLfk/TVPwwYOTfaI/AAAAAAAAAXo/ehMvg2QmwJc/s72-c/sphereoutline.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-7587890811464000766</id><published>2011-02-07T23:46:00.000+08:00</published><updated>2011-02-07T23:46:30.252+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><category scheme='http://www.blogger.com/atom/ns#' term='fluid'/><title type='text'>Ripple effect in WebGL</title><content type='html'>&lt;script id="shader-vs" type="x-shader/x-vertex"&gt;//===================================================================================//Vertex Shader//===================================================================================  attribute vec3 aVertexPosition;  void main(void) {    gl_Position = vec4(aVertexPosition, 1.0);  }&lt;/script&gt;&lt;br /&gt;&lt;script id="shader-fs-ripple" type="x-shader/x-fragment"&gt;//Script by Adrian Boeing//www.adrianboeing.com#ifdef GL_ESprecision highp float;#endifuniform float time;uniform vec2 resolution;uniform sampler2D tex;void main(void) {vec2 cPos = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;float cLength = length(cPos);vec2 uv = gl_FragCoord.xy/resolution.xy+(cPos/cLength)*cos(cLength*12.0-time*4.0)*0.03;vec3 col = texture2D(tex,uv).xyz;gl_FragColor = vec4(col,1.0);}&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;//===================================================================================//Javascript code for setting up WebGL//===================================================================================  var canvas;  var startTime;   var gl;  var squareVertexPositionBuffer;  var shaderProgram;  var neheTexture;  function initGL(canvas) {    try {      gl = canvas.getContext("experimental-webgl");      gl.viewportWidth = canvas.width;      gl.viewportHeight = canvas.height;    } catch(e) {    }    if (!gl) {      alert("Could not initialise WebGL!");    }    startTime = (new Date()).getTime();  }  function getShader(gl, id) {    var shaderScript = document.getElementById(id);    if (!shaderScript) {      return null;    }    var str = "";    var k = shaderScript.firstChild;    while (k) {      if (k.nodeType == 3) {        str += k.textContent;      }      k = k.nextSibling;    }    var shader;    if (shaderScript.type == "x-shader/x-fragment") {      shader = gl.createShader(gl.FRAGMENT_SHADER);    } else if (shaderScript.type == "x-shader/x-vertex") {      shader = gl.createShader(gl.VERTEX_SHADER);    } else {      return null;    }    gl.shaderSource(shader, str);    gl.compileShader(shader);    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {      alert(gl.getShaderInfoLog(shader));      return null;    }    return shader;  }  function initShaders_ripple() {    var fragmentShader = getShader(gl, "shader-fs-ripple");    //var fragmentShader = getShader(gl, "simple-fs");    var vertexShader = getShader(gl, "shader-vs");    shaderProgram = gl.createProgram();    gl.attachShader(shaderProgram, vertexShader);    gl.attachShader(shaderProgram, fragmentShader);    gl.linkProgram(shaderProgram);    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {      alert("Could not initialise shaders");    }    gl.useProgram(shaderProgram);    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);    shaderProgram.pResolutionUniform = gl.getUniformLocation(shaderProgram, "resolution");    shaderProgram.pTimeUniform = gl.getUniformLocation(shaderProgram, "time");  }  function setUniforms_ripple() {     gl.activeTexture(gl.TEXTURE0);    gl.bindTexture(gl.TEXTURE_2D, neheTexture);    gl.uniform1i(shaderProgram.samplerUniform, 0);      gl.uniform2f(shaderProgram.pResolutionUniform, canvas.width, canvas.height);    var time = (new Date()).getTime();    gl.uniform1f(shaderProgram.pTimeUniform, (time - startTime) / 1000.0);  }  function initBuffers() {    squareVertexPositionBuffer = gl.createBuffer();    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    vertices = [         1.0,  1.0,  0.0,        -1.0,  1.0,  0.0,         1.0, -1.0,  0.0,        -1.0, -1.0,  0.0    ];    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);    squareVertexPositionBuffer.itemSize = 3;    squareVertexPositionBuffer.numItems = 4;  }  function onWindowResize( event ) {    canvas.width = window.innerWidth;    canvas.height = window.innerHeight;    gl.viewport( 0, 0, canvas.width, canvas.height );  }    function handleLoadedTexture(texture) {    gl.bindTexture(gl.TEXTURE_2D, texture);    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);    gl.bindTexture(gl.TEXTURE_2D, null);  }   function initTexture() {    neheTexture = gl.createTexture();    neheTexture.image = new Image();    neheTexture.image.onload = function() {      handleLoadedTexture(neheTexture)    }    neheTexture.image.src = "http://www.iquilezles.org/apps/shadertoy/presets/tex1.jpg";   }      function drawScene() {    //gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);    gl.clear(gl.COLOR_BUFFER_BIT);    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);    setUniforms_ripple();    gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);  }  function webGLStart_ripple() {    canvas = document.getElementById("my-canvas-ripple");    initGL(canvas);    initShaders_ripple()    initBuffers();    initTexture();    gl.clearColor(0.0, 0.0, 0.0, 1.0);    gl.disable(gl.DEPTH_TEST);    setInterval(drawScene, 16);  }  &lt;/script&gt;&lt;br /&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;There is really nothing special to the ripple effect, in essence it is just an evaluation of the &lt;a href="http://en.wikipedia.org/wiki/Sombrero_function"&gt;sombrero function&lt;/a&gt;. This is just a 2D version of the &lt;a href="http://en.wikipedia.org/wiki/Sinc_function"&gt;sinc function&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&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/_nHcDA3NyAms/TVASXEcNPtI/AAAAAAAAAXc/iP8BahJqIDY/s1600/sinc.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TVASXEcNPtI/AAAAAAAAAXc/iP8BahJqIDY/s1600/sinc.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Below is a graph of the sin function, followed by sinc.&lt;br /&gt;&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/_nHcDA3NyAms/TVAScKmBZVI/AAAAAAAAAXg/jXXQPCV79tk/s1600/sinsinc.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="153" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TVAScKmBZVI/AAAAAAAAAXg/jXXQPCV79tk/s400/sinsinc.png" 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;Left: sin(x); &amp;nbsp; Right: sin(x) / x&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Extending this to 2D we have:&lt;br /&gt;&lt;pre&gt;r = sqrt (x*x + y*y);&lt;br /&gt;z = sin (r) / r;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Plotting this as (x,y,z) we have the sombrero function:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TVASrH5bjQI/AAAAAAAAAXk/eZP-o4C--ZA/s1600/sombrero.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="213" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TVASrH5bjQI/AAAAAAAAAXk/eZP-o4C--ZA/s320/sombrero.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;To turn it into a ripple-like looking effect we just need to scale down the "height" of the function, and animate it by adding time into the sin term to generate a repeating pulse. The complete GLSL code is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;#ifdef GL_ES&lt;br /&gt;precision highp float;&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;uniform float time;&lt;br /&gt;uniform vec2 resolution;&lt;br /&gt;uniform sampler2D tex;&lt;br /&gt;&lt;br /&gt;void main(void) {&lt;br /&gt;vec2 cPos = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;&lt;br /&gt;float cLength = length(cPos);&lt;br /&gt;&lt;br /&gt;vec2 uv = gl_FragCoord.xy/resolution.xy+(cPos/cLength)*cos(cLength*12.0-time*4.0)*0.03;&lt;br /&gt;vec3 col = texture2D(tex,uv).xyz;&lt;br /&gt;&lt;br /&gt;gl_FragColor = vec4(col,1.0);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;form&gt;&lt;input onclick="webGLStart_ripple()" type="button" value="Click me!" /&gt; &lt;/form&gt;&lt;canvas height="300" id="my-canvas-ripple" width="400"&gt; Your browser doesn't appear to support the HTML5 &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element. &lt;/canvas&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/17188375-7587890811464000766?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/7587890811464000766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=7587890811464000766' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7587890811464000766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7587890811464000766'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/02/ripple-effect-in-webgl.html' title='Ripple effect in WebGL'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/TVASXEcNPtI/AAAAAAAAAXc/iP8BahJqIDY/s72-c/sinc.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-1528226346413168888</id><published>2011-02-06T22:30:00.000+08:00</published><updated>2011-02-06T22:30:29.580+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='raytracing'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><title type='text'>Despaire by Iguana ported to Mac OSX</title><content type='html'>One of my favourite old demos is &lt;a href="http://www.pouet.net/prod.php?which=365"&gt;Despair by Iguana&lt;/a&gt;.  It features a number of nice effects including realtime raytracing, blended particles, and many more effects that were ahead of its time (It was released in 1996!). The source code for the demo was released and &lt;a href="http://www.pouet.net/prod.php?which=8041"&gt;ported to 32bit by David 'mac' from ThreePixels&lt;/a&gt;. So I took it upon myself to port it from 32bit windows to 64bit OSX / *nix.  &lt;br /&gt;&lt;ol&gt;&lt;li&gt;First I translated David's version to VS2010 and ported it to use &lt;a href="http://www.libsdl.org/"&gt;SDL&lt;/a&gt; and the latest &lt;a href="http://www.un4seen.com/"&gt;BASS&lt;/a&gt;, compiling it on windows, to ensure it was all running.&lt;br /&gt;&lt;li&gt;I stripped out all the non-portable assembly code. Unfortunately none of this code was commented, and the few comments that were in there, were all in spanish. (I think)&lt;br /&gt;&lt;li&gt;I installed &lt;a href="http://software.intel.com/en-us/articles/intel-software-evaluation-center/"&gt;Intel C++ Composer XE 2011 for Mac OS* X (The Intel C++ compiler on OSX)&lt;/a&gt;, to keep the code compatible with VS as far as possible, and created a makefile. &lt;br /&gt;&lt;li&gt;I ported the code across to OSX. Nothing too special here, replacing a few windows and DOS function calls with their POSIX equivalents. This part of the port followed the same process as porting any other windows application to another platform. (I'd already done the port to SDL)&lt;br /&gt;&lt;li&gt;I requested (and received! Thanks Ian!) a 64bit copy of BASS for OSX.&lt;br /&gt;&lt;li&gt;Success! A stripped down version of Despair ran on OSX, very few effects actually worked. Now the fun (pain?) could begin.&lt;br /&gt;&lt;li&gt;I looked through all the assembly code and realised quickly that I would never be able to port it all. Instead, I figured I would take an educated guess at the functionality.&lt;br /&gt;&lt;li&gt;I noted some assembly code "RenderBandScan" and took a quick look and spotted a:&lt;br /&gt;&lt;pre&gt;and eax,0F0F0F0F0h&lt;br /&gt;&lt;/pre&gt;Immediately, I recalled the old trick of using bitwise and and shifts to quickly sum 4 pixels at once, and re-implemented this in a simple C loop. &lt;br /&gt;&lt;li&gt;The next routine was "AADump", a little trickier this time, but again a well known pattern:&lt;br /&gt;&lt;pre&gt; mov cl,[esi+1]&lt;br /&gt; mov bl,[esi+320]&lt;br /&gt; add eax,ecx&lt;br /&gt; mov dl,[esi+321]&lt;br /&gt; add eax,ebx&lt;br /&gt; add ecx,edx&lt;br /&gt; add eax,edx&lt;br /&gt; mov dl,[esi+2]&lt;br /&gt; shr eax,2&lt;br /&gt;&lt;/pre&gt;The pattern of adds and a shift for quickly "blurring" an image, from that basis I just re-implemented a blur-copy routine, and all was well.&lt;br /&gt;&lt;li&gt;I came across the cryptic "DumpScanASM" routine. Luckily, there was a section of c-code commented out that I could just drop back in to replace this. Phew!&lt;br /&gt;&lt;li&gt;The next function was "RenderScan". The name was quite self-explanatory, however I noted a fair bit of odd '127' in there. Knowing the effect was alpha blending some blobs, I deduced the C code:&lt;br /&gt;&lt;code&gt;&lt;br /&gt; for (i=0;i&lt;np;i++) {  sum = dest[i]+src[i];  if (sum&gt;127)&lt;br /&gt;   sum = 127;&lt;br /&gt;  dest[i]=sum;&lt;br /&gt; }&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;li&gt;The second last effect that needed translation from assembly to C was "FB_Draw320x200". This was a bit cryptic, but essentially it was a fixed-point texture sampling routine with a number of clever bit-shifts. I didn't quite get this one converted correctly.&lt;br /&gt;&lt;li&gt;Finally, the greets section is a rotozoomer, texture mapping and blending routine written in pure assembly. This is where I call it a day. I'm not converting this beast! (If anyone else wants to you will need to re-code: DrawGrScan, and VSTM_DumpScan2000.. good luck!)&lt;br /&gt;&lt;/ol&gt;&lt;a href="http://www.adrianboeing.com/files/despaire_osx.zip"&gt;Here is a zip of the OSX executable for the Despair/Iguana demo along with the ported source code and make files.&lt;/a&gt;Youtube video below:&lt;iframe title="YouTube video player" width="425" height="349" src="http://www.youtube.com/embed/L_lD7iqG8nA" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-1528226346413168888?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/1528226346413168888/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=1528226346413168888' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/1528226346413168888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/1528226346413168888'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/02/despaire-by-iguana-ported-to-mac-osx.html' title='Despaire by Iguana ported to Mac OSX'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/L_lD7iqG8nA/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-4838015725111454193</id><published>2011-02-02T22:03:00.000+08:00</published><updated>2011-02-02T22:03:35.202+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><title type='text'>Ported Trip! (4k intro) to OSX</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TUlj7CIOv7I/AAAAAAAAAXQ/3kyGkZ8Mkk4/s1600/trip.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TUlj7CIOv7I/AAAAAAAAAXQ/3kyGkZ8Mkk4/s320/trip.gif" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;There are very few products from the &lt;a href="http://en.wikipedia.org/wiki/Demoscene"&gt;demoscene&lt;/a&gt; that are available on Mac OSX.&lt;br /&gt;&lt;br /&gt;In preparation for some more challenging ports of old demoscene products across to OSX I thought I would start with one of my own productions. Unfortunately, I historically used DirectX, but I did do one OpenGL production, &lt;a href="http://pouet.net/prod.php?which=31457"&gt;Trip! for Syntax 2007&lt;/a&gt;. And now, the &lt;a href="http://www.adrianboeing.com/files/trip.zip"&gt;Mac OSX (Intel) port of Trip! for Syntax 2007&lt;/a&gt;, unfortunately nowhere near 4k anymore. (Warning: Plenty of black/white flashes, the &lt;a href="http://en.wikipedia.org/wiki/Afterimage_effect"&gt;illusions&lt;/a&gt; will only work if you stare at the center of the screen)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-4838015725111454193?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/4838015725111454193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=4838015725111454193' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/4838015725111454193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/4838015725111454193'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/02/ported-trip-4k-intro-to-osx.html' title='Ported Trip! (4k intro) to OSX'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nHcDA3NyAms/TUlj7CIOv7I/AAAAAAAAAXQ/3kyGkZ8Mkk4/s72-c/trip.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-1583354890508161877</id><published>2011-01-31T21:35:00.000+08:00</published><updated>2011-01-31T21:35:16.172+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><title type='text'>Twist Effect in WebGL</title><content type='html'>&lt;script id="shader-vs" type="x-shader/x-vertex"&gt;//===================================================================================//Vertex Shader//===================================================================================  attribute vec3 aVertexPosition;  void main(void) {    gl_Position = vec4(aVertexPosition, 1.0);  }&lt;/script&gt;&lt;br /&gt;&lt;script id="shader-fs-twist" type="x-shader/x-fragment"&gt;//Script by Adrian Boeing//www.adrianboeing.com#ifdef GL_ESprecision highp float;#endifuniform vec2 resolution;uniform float time;uniform sampler2D tex;void main(void){    vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;    vec2 uv;       float a = atan(p.y,p.x) / (2.0*3.1416);    float r = sqrt(dot(p,p))/sqrt(2.0);    uv.x = r + time * 0.3;    uv.y = a+r - time*0.1;    vec3 col =  texture2D(tex,uv).xyz;    gl_FragColor = vec4(col,1.0);}&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;//===================================================================================//Javascript code for setting up WebGL//===================================================================================  var canvas;  var startTime;   var gl;  var squareVertexPositionBuffer;  var shaderProgram;  var neheTexture;  function initGL(canvas) {    try {      gl = canvas.getContext("experimental-webgl");      gl.viewportWidth = canvas.width;      gl.viewportHeight = canvas.height;    } catch(e) {    }    if (!gl) {      alert("Could not initialise WebGL!");    }    startTime = (new Date()).getTime();  }  function getShader(gl, id) {    var shaderScript = document.getElementById(id);    if (!shaderScript) {      return null;    }    var str = "";    var k = shaderScript.firstChild;    while (k) {      if (k.nodeType == 3) {        str += k.textContent;      }      k = k.nextSibling;    }    var shader;    if (shaderScript.type == "x-shader/x-fragment") {      shader = gl.createShader(gl.FRAGMENT_SHADER);    } else if (shaderScript.type == "x-shader/x-vertex") {      shader = gl.createShader(gl.VERTEX_SHADER);    } else {      return null;    }    gl.shaderSource(shader, str);    gl.compileShader(shader);    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {      alert(gl.getShaderInfoLog(shader));      return null;    }    return shader;  }  function initShaders_twist() {    var fragmentShader = getShader(gl, "shader-fs-twist");    //var fragmentShader = getShader(gl, "simple-fs");    var vertexShader = getShader(gl, "shader-vs");    shaderProgram = gl.createProgram();    gl.attachShader(shaderProgram, vertexShader);    gl.attachShader(shaderProgram, fragmentShader);    gl.linkProgram(shaderProgram);    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {      alert("Could not initialise shaders");    }    gl.useProgram(shaderProgram);    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);    shaderProgram.pResolutionUniform = gl.getUniformLocation(shaderProgram, "resolution");    shaderProgram.pTimeUniform = gl.getUniformLocation(shaderProgram, "time");  }  function setUniforms_twist() {     gl.activeTexture(gl.TEXTURE0);    gl.bindTexture(gl.TEXTURE_2D, neheTexture);    gl.uniform1i(shaderProgram.samplerUniform, 0);      gl.uniform2f(shaderProgram.pResolutionUniform, canvas.width, canvas.height);    var time = (new Date()).getTime();    gl.uniform1f(shaderProgram.pTimeUniform, (time - startTime) / 1000.0);  }  function initBuffers() {    squareVertexPositionBuffer = gl.createBuffer();    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    vertices = [         1.0,  1.0,  0.0,        -1.0,  1.0,  0.0,         1.0, -1.0,  0.0,        -1.0, -1.0,  0.0    ];    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);    squareVertexPositionBuffer.itemSize = 3;    squareVertexPositionBuffer.numItems = 4;  }  function onWindowResize( event ) {    canvas.width = window.innerWidth;    canvas.height = window.innerHeight;    gl.viewport( 0, 0, canvas.width, canvas.height );  }    function handleLoadedTexture(texture) {    gl.bindTexture(gl.TEXTURE_2D, texture);    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);    gl.bindTexture(gl.TEXTURE_2D, null);  }   function initTexture() {    neheTexture = gl.createTexture();    neheTexture.image = new Image();    neheTexture.image.onload = function() {      handleLoadedTexture(neheTexture)    }    neheTexture.image.src = "http://www.iquilezles.org/apps/shadertoy/presets/tex3.jpg";   }      function drawScene() {    //gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);    gl.clear(gl.COLOR_BUFFER_BIT);    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);    setUniforms_twist();    gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);  }  function webGLStart_twist() {    canvas = document.getElementById("my-canvas-twist");    initGL(canvas);    initShaders_twist()    initBuffers();    initTexture();    gl.clearColor(0.0, 0.0, 0.0, 1.0);    gl.disable(gl.DEPTH_TEST);    setInterval(drawScene, 16);  }  &lt;/script&gt;&lt;br /&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;The twist/twirl effect is achieved with a combination of techniques I've already discussed:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The &lt;a href="http://adrianboeing.blogspot.com/2011/01/xor-demoeffect-in-webgl.html"&gt;circle equation, from the XOR bitplasma example&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The &lt;a href="http://adrianboeing.blogspot.com/2011/01/webgl-tunnel-effect-explained.html"&gt;angle for each pixel, from the Tunnel example&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/TUa3FInMZgI/AAAAAAAAAW0/C2ow39AIOxM/s1600/r.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TUa3FInMZgI/AAAAAAAAAW0/C2ow39AIOxM/s320/r.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Radius (r)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Combining these will give us a 'twisting' effect. Unfortunately, this is almost impossible to explain without pictures. &lt;br /&gt;&lt;br /&gt;Unlike the previous examples where I used shaders to explain each component, it will be easier to explain this with some graphs. In the graph each color represents a different height, so from our circle-equation we get: &lt;br /&gt;&lt;code&gt; float r = sqrt(dot(p,p))/sqrt(2.0); &lt;/code&gt; &lt;br /&gt;&lt;br /&gt;From the tangent-equation we get: &lt;br /&gt;&lt;code&gt; float a = atan(p.y,p.x) / (2.0*3.1416); &lt;/code&gt; &lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TUa3VPlrm3I/AAAAAAAAAW4/IoEfUnU3jcc/s1600/a.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TUa3VPlrm3I/AAAAAAAAAW4/IoEfUnU3jcc/s320/a.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Angle (a)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Twisting is essentially a spiral, and we can generate a spiral by stepping out a constant amount towards the radius as we progress around a circle. For example, we start at 0 degrees, at 0% of a step away, then move to 45 degrees at 12.5% of a step towards the radius, then move to 90 degrees at 25% of the radius, and so on. &lt;br /&gt;&lt;br /&gt;This is shown in the image below:  &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TUa3jL5_luI/AAAAAAAAAW8/5pTB03kHSeA/s1600/spiral.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="196" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TUa3jL5_luI/AAAAAAAAAW8/5pTB03kHSeA/s200/spiral.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Now, to generate a twist we can simply add our constant step away (in the form of the 'r'(radius) graph/image) with our rotation around a circle (in the form of the 'a'(angle) graph/image). This generates our final graph:   &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/TUa3_gTdcII/AAAAAAAAAXA/WRdfgBU26Rk/s1600/ra.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TUa3_gTdcII/AAAAAAAAAXA/WRdfgBU26Rk/s320/ra.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;We use this equation to sample from our texture. &lt;br /&gt;In GLSL shader code, we have: &lt;br /&gt;&lt;code&gt; &lt;br /&gt;uniform vec2 resolution; &lt;br /&gt;uniform sampler2D tex;  &lt;br /&gt;void main(void) {     &lt;br /&gt;vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;&lt;br /&gt;vec2 uv;         &lt;br /&gt;float a = atan(p.y,p.x) / (2.0*3.1416);&lt;br /&gt;float r = sqrt(dot(p,p))/sqrt(2.0);&lt;br /&gt;uv.x = r;&lt;br /&gt;uv.y = a+r;&lt;br /&gt;vec3 col =  texture2D(tex,uv).xyz;&lt;br /&gt;gl_FragColor = vec4(col,1.0);&lt;br /&gt;} &lt;br /&gt;&lt;/code&gt; &lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TUa4jwCU_0I/AAAAAAAAAXI/WRx1zDdBWic/s1600/texture.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="200" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TUa4jwCU_0I/AAAAAAAAAXI/WRx1zDdBWic/s200/texture.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Square color texture&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;To animate our spiral and make it spin, we just need to add a offset to our "a+r" value. To make the spiral scroll the texture "inwards" we can just add an offset to the "r" value.&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TUa4Xi0bE3I/AAAAAAAAAXE/5T-pl259AB4/s1600/twist.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="146" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TUa4Xi0bE3I/AAAAAAAAAXE/5T-pl259AB4/s200/twist.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Twist with the square color texture&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;This will give us our final animating spiral:&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;form&gt;&lt;input onclick="webGLStart_twist()" type="button" value="Click me!" /&gt; &lt;br /&gt;&lt;/form&gt;&lt;br /&gt;&lt;canvas height="300" id="my-canvas-twist" width="400"&gt; Your browser doesn't appear to support the HTML5 &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element. &lt;/canvas&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-1583354890508161877?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/1583354890508161877/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=1583354890508161877' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/1583354890508161877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/1583354890508161877'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/01/twist-effect-in-webgl.html' title='Twist Effect in WebGL'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/TUa3FInMZgI/AAAAAAAAAW0/C2ow39AIOxM/s72-c/r.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-2552385125294722882</id><published>2011-01-28T20:22:00.000+08:00</published><updated>2011-01-28T20:22:42.871+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='raytracing'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><title type='text'>Raycasting two planes in WebGL</title><content type='html'>&lt;script id="shader-vs" type="x-shader/x-vertex"&gt;//===================================================================================//Vertex Shader//===================================================================================  attribute vec3 aVertexPosition;  void main(void) {    gl_Position = vec4(aVertexPosition, 1.0);  }&lt;/script&gt;&lt;br /&gt;&lt;script id="shader-fs-planes" type="x-shader/x-fragment"&gt;//Script by Adrian Boeing//www.adrianboeing.com#ifdef GL_ESprecision highp float;#endifuniform vec2 resolution;uniform float time;uniform sampler2D tex;void main(void){    vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;    vec2 uv;         float h = 0.25;    uv.x = h*p.x / p.y;    uv.y = 0.1*time + h / abs(p.y);    gl_FragColor = vec4(texture2D(tex,uv).xyz * p.y*p.y, 1.0);}&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;//===================================================================================//Javascript code for setting up WebGL//===================================================================================  var canvas;  var startTime;   var gl;  var squareVertexPositionBuffer;  var shaderProgram;  var neheTexture;  function initGL(canvas) {    try {      gl = canvas.getContext("experimental-webgl");      gl.viewportWidth = canvas.width;      gl.viewportHeight = canvas.height;    } catch(e) {    }    if (!gl) {      alert("Could not initialise WebGL!");    }    startTime = (new Date()).getTime();  }  function getShader(gl, id) {    var shaderScript = document.getElementById(id);    if (!shaderScript) {      return null;    }    var str = "";    var k = shaderScript.firstChild;    while (k) {      if (k.nodeType == 3) {        str += k.textContent;      }      k = k.nextSibling;    }    var shader;    if (shaderScript.type == "x-shader/x-fragment") {      shader = gl.createShader(gl.FRAGMENT_SHADER);    } else if (shaderScript.type == "x-shader/x-vertex") {      shader = gl.createShader(gl.VERTEX_SHADER);    } else {      return null;    }    gl.shaderSource(shader, str);    gl.compileShader(shader);    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {      alert(gl.getShaderInfoLog(shader));      return null;    }    return shader;  }  function initShadersPlanes() {    var fragmentShader = getShader(gl, "shader-fs-planes");    //var fragmentShader = getShader(gl, "simple-fs");    var vertexShader = getShader(gl, "shader-vs");    shaderProgram = gl.createProgram();    gl.attachShader(shaderProgram, vertexShader);    gl.attachShader(shaderProgram, fragmentShader);    gl.linkProgram(shaderProgram);    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {      alert("Could not initialise shaders");    }    gl.useProgram(shaderProgram);    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);    shaderProgram.pResolutionUniform = gl.getUniformLocation(shaderProgram, "resolution");    shaderProgram.pTimeUniform = gl.getUniformLocation(shaderProgram, "time");  }  function setUniformsPlanes() {     gl.activeTexture(gl.TEXTURE0);    gl.bindTexture(gl.TEXTURE_2D, neheTexture);    gl.uniform1i(shaderProgram.samplerUniform, 0);      gl.uniform2f(shaderProgram.pResolutionUniform, canvas.width, canvas.height);    var time = (new Date()).getTime();    gl.uniform1f(shaderProgram.pTimeUniform, (time - startTime) / 1000.0);  }  function initBuffers() {    squareVertexPositionBuffer = gl.createBuffer();    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    vertices = [         1.0,  1.0,  0.0,        -1.0,  1.0,  0.0,         1.0, -1.0,  0.0,        -1.0, -1.0,  0.0    ];    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);    squareVertexPositionBuffer.itemSize = 3;    squareVertexPositionBuffer.numItems = 4;  }  function onWindowResize( event ) {    canvas.width = window.innerWidth;    canvas.height = window.innerHeight;    gl.viewport( 0, 0, canvas.width, canvas.height );  }    function handleLoadedTexture(texture) {    gl.bindTexture(gl.TEXTURE_2D, texture);    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);    gl.bindTexture(gl.TEXTURE_2D, null);  }   function initTexture() {    neheTexture = gl.createTexture();    neheTexture.image = new Image();    neheTexture.image.onload = function() {      handleLoadedTexture(neheTexture)    }    neheTexture.image.src = "http://www.iquilezles.org/apps/shadertoy/presets/tex2.jpg";   }      function drawScene() {    //gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);    gl.clear(gl.COLOR_BUFFER_BIT);    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);    setUniformsPlanes();    gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);  }  function webGLStartPlanes() {    canvas = document.getElementById("my-canvas-planes");    initGL(canvas);    initShadersPlanes()    initBuffers();    initTexture();    gl.clearColor(0.0, 0.0, 0.0, 1.0);    gl.disable(gl.DEPTH_TEST);    setInterval(drawScene, 16);  }  &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I always implemented this effect by actually writing a complete raytracer/caster, however the version of this effect in &lt;a href="http://www.iquilezles.org/apps/shadertoy/"&gt;ShaderToy&lt;/a&gt; greatly simplifies this effect using some old fashioned trigonometry. With some help from my old democoding partner Fractoid we generated a mathematical explanation for this routine. &lt;br /&gt;&lt;br /&gt;In essence we use the properties of self-similar triangles to find the intersection distance from the viewer to the plane (see image below).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TUKymXoIPAI/AAAAAAAAAWs/Dg71nH1YqPw/s1600/planes-camera.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="165" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TUKymXoIPAI/AAAAAAAAAWs/Dg71nH1YqPw/s400/planes-camera.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The camera is shown in red, and the ray from the viewer to the plane is shown in green.  The height of the plane above the viewer is 'h', and the distance along the plane to the intersection point is 'd'. We can use &lt;a href="http://adrianboeing.blogspot.com/2011/01/webgl-tunnel-effect-explained.html"&gt;our friend from last time, the tangent function&lt;/a&gt;, to find the intersection point.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TUKy5W7yC5I/AAAAAAAAAWw/LvPyUS0P0lw/s1600/tan.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TUKy5W7yC5I/AAAAAAAAAWw/LvPyUS0P0lw/s1600/tan.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;For the lower triangle, if we assume one unit of travel (x) then the angle (theta) will be y / 1.&lt;br /&gt;&lt;pre&gt;tan(theta) = y/1;&lt;br /&gt;&lt;/pre&gt;For the upper triangle, theta will be h / d.&lt;br /&gt;&lt;pre&gt;tan(theta) = h/d;&lt;br /&gt;&lt;/pre&gt;Since the triangles are similar triangles, both theta values are the same, so we can equate these two equations. That is:&lt;br /&gt;&lt;pre&gt;y / 1 = h / d&lt;br /&gt;y = h / d&lt;br /&gt;d = h / y&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, to solve the same problem but flipped by 90 degrees for the horizontal axis we have the same formulation, except we no longer have a unit travel distance, but 'x' instead. This gives:&lt;br /&gt;&lt;pre&gt;y / x = h / d&lt;br /&gt;y = h.x / d&lt;br /&gt;d = h.x / y&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now we can plug these into our texture map to give us the overall effect:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;uniform vec2 resolution;&lt;br /&gt;uniform float time;&lt;br /&gt;uniform sampler2D tex;&lt;br /&gt;&lt;br /&gt;void main(void)&lt;br /&gt;{&lt;br /&gt;vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;&lt;br /&gt;vec2 uv;&lt;br /&gt;&lt;br /&gt;float h = 0.25;&lt;br /&gt;uv.x = h*p.x / p.y;&lt;br /&gt;uv.y = 0.1*time + h / abs(p.y);&lt;br /&gt;&lt;br /&gt;gl_FragColor = vec4(texture2D(tex,uv).xyz * p.y*p.y, 1.0);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/div&gt;&lt;br /&gt;You can see the result below. (You will need a WebGL enabled browser)&lt;br /&gt;&lt;form&gt;&lt;input onclick="webGLStartPlanes()" type="button" value="Click me!" /&gt; &lt;/form&gt;&lt;canvas height="300" id="my-canvas-planes" width="400"&gt; Your browser doesn't appear to support the HTML5 &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element. &lt;/canvas&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-2552385125294722882?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/2552385125294722882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=2552385125294722882' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/2552385125294722882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/2552385125294722882'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/01/raycasting-two-planes-in-webgl.html' title='Raycasting two planes in WebGL'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nHcDA3NyAms/TUKymXoIPAI/AAAAAAAAAWs/Dg71nH1YqPw/s72-c/planes-camera.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-5331307907459081220</id><published>2011-01-28T13:12:00.000+08:00</published><updated>2011-01-28T13:12:23.474+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='education'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><title type='text'>Disruptive Innovations</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TUJPYbU8nxI/AAAAAAAAAWk/srXlxCVCjf4/s1600/innovation.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TUJPYbU8nxI/AAAAAAAAAWk/srXlxCVCjf4/s200/innovation.jpg" width="184" /&gt;&lt;/a&gt;&lt;/div&gt;Everyone wants to build a &lt;a href="http://en.wikipedia.org/wiki/Disruptive_technology"&gt; disruptive technology&lt;/a&gt; or a disruptive business. But what does that really mean? An article by &lt;a href="http://www.blogger.com/%E2%80%9Dhttp://www.google.com/search?q=Foundations+for+Growth:+How+To+Identify+and+Build+Disruptive+New+Businessess%E2%80%9D"&gt;Clayton Christensen, Mark Johnson and Darrell Rigby 'Foundations for Growth: How To Identify and Build Disruptive New Businesses' &lt;/a&gt; provides a description of disruptive, and identifies key requirements for disruptive businesses. &lt;br /&gt;&lt;br /&gt;Christensen et al. distinguish disruptive innovations from staining innovations in that the latter only target existing customers in established markets. In contrast, disruptive innovations create new markets and generate new ways of doing business that effects established markets. Further clarifications:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Industry incumbents aren't always the first to market with a sustaining innovation, but they almost always end up on top due to superior resources and high stakes.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Innovations that help incumbent companies sell better products to their best customers are sustaining, not disruptive.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Established businesses move towards the more profitable customers (see above), providing asymmetric motivation for entrants to attack less profitable customers (down-market)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;'Down-market' are typically small and undefined but hold the best prospects for growth&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TUJP3ACA0pI/AAAAAAAAAWo/pbI2nVldebk/s1600/disruptive_sustain.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TUJP3ACA0pI/AAAAAAAAAWo/pbI2nVldebk/s320/disruptive_sustain.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;According to the article, new growth business has a 10x better chance of success with a disruptive strategy.  How do you know if you can follow a disruptive strategy? In essence the recommended requirement is a open, simple, low-cost product.  &lt;br /&gt;&lt;ol&gt;&lt;li&gt; Can you create a new market base?&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Does it enable customers who could not previously DIY for lack of money or skills? That is, can it become mainstream rather than specialised?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Is it targeted at customers who want a simple product?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Will it allow customers to do more easily and effectively what they are already trying to do? i.e. Is it fulfilling an existing need/want, rather than creating a new one?&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Can you disrupt from the low end?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Are prevailing performance good enough? If not, then a simpler product will not succeed.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Do you have a business model that targets thin profit margins and high &lt;a href="http://en.wikipedia.org/wiki/Asset_turnover"&gt;net asset turns&lt;/a&gt;. Do competitors already outsource fabrication and assembly to the lowest-cost sources?&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;Now that you know your innovation has the potential to be disruptive, do you have the resources, processes and values you require for success? &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Resources: Do you have the best people and sufficient cash? A manager who is radically different from those established with core business who has the correct experience? Are you aware of the challenges the manager will face? Too much cash can allow bloat that weakens the product (remember our tight profit margins), too little and the product may never see the light of day.  &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Processes and Values: Traditional and established processes can hamper a disruptive enterprise, an independent business unit that emphasises the key values of simplicity and low-cost is best.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;For established companies you will want to: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Start before you need to grow, while you can afford it (ie: while your company is still growing)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Create an aggregate project plan with strategic objectives&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Train employees to scout for well positioned small companies that will help accelerate and improve your disruptive product&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;A successful disruptive product should generate profits almost immediately, but needs to be cautious to not out-grow your capabilities: new markets take time to emerge. &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-5331307907459081220?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/5331307907459081220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=5331307907459081220' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5331307907459081220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5331307907459081220'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/01/disruptive-innovations.html' title='Disruptive Innovations'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nHcDA3NyAms/TUJPYbU8nxI/AAAAAAAAAWk/srXlxCVCjf4/s72-c/innovation.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-5357660253585804610</id><published>2011-01-26T12:20:00.000+08:00</published><updated>2011-01-26T12:20:00.001+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='compilers'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><title type='text'>Executable compression</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/TT-g2MOrTlI/AAAAAAAAAWg/syKArgqcQCE/s1600/compressdata.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="180" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TT-g2MOrTlI/AAAAAAAAAWg/syKArgqcQCE/s200/compressdata.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;Packing an executable to a smaller size is a common task, and the compression algorithms share a lot in common with good text compression systems. Most good executable compression algorithms have some method of interpreting, filtering or transforming the program instructions to a more compressible format. The most well-known compression algorithms are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Run-length_encoding"&gt;Run Length Encoding&lt;/a&gt; - where multiples of the same in-order data are represented in a compressed form. For example, the word "beekeeper", may be represented as "b(2x e)k(2x e)per", with an appropriate coding results in a reduction in size. This kind of compression works well on 8bit images and is found in image formats such as BMP.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Huffman_coding"&gt;Huffman compression&lt;/a&gt; - each code is represented with a number of bits proportional to the frequency of occurrence.  For example, we could represent vowels with shorter bits, and consonants with longer bit sequences, or "e" could be represented with "1" and every other character with 0 plus the usual 8 bits then "beekeeper" would come to "b11k11p1r" in a total of 4x 9 bits and 5x 1 bit totalling to 41 bits rather than 72 bits.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/LZ77_and_LZ78"&gt;Lempel-Ziv (LZ)&lt;/a&gt; - a dictionary of all previous data is kept and references are made back to the history of the data. For example, "beekeeper" could be represented as "be(-1,1)k(-3,2)p(-2,1),r" which translates to "be" plus the same character as before (-1) and one (1) byte of it, resulting in "bee", then "k", followed by the occurrence three characters before (-3) and (2) bytes of it, resulting in "beekee", etc.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Arithmetic_code"&gt;Arithmetic coding&lt;/a&gt; is &lt;a href="http://cbloomrants.blogspot.com/2010/08/08-11-10-huffman-arithmetic-equivalence.html"&gt;similar to huffman coding (and explained very concisely by Charles Bloom)&lt;/a&gt;, in essence it also assigns bits according to the probability of occurrence (as a "floating point" number), and then re-scales/encodes the probabilities to fixed-point.  &lt;a href="http://www.arturocampos.com/ac_arithmetic.html"&gt;Arturo ("Dario Phong") Campos&lt;/a&gt; has a concise explanation.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/PAQ"&gt;PAQ&lt;/a&gt; - this is generally considered the &lt;a href="http://www.maximumcompression.com/data/summary_sf.php"&gt;state-of-the-art&lt;/a&gt; compression algorithm. It uses &lt;a href="http://en.wikipedia.org/wiki/Context_mixing"&gt;conditional probabilistic models&lt;/a&gt; to achieve optimal compression.  &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;There is plenty of source code around the web for these algorithms, but the &lt;a href="http://bcl.comli.eu/"&gt;Basic Compression Library&lt;/a&gt; provides routines for RLE (Run Length Encoding), Huffman, Rice, Lempel-Ziv (LZ77) and Shannon-Fano compression algorithms. And &lt;a href="http://mattmahoney.net/dc/"&gt;Matt Mahoney&lt;/a&gt; maintains the PAQ algorithms.   There are also quite a few general executable compressors available including &lt;a href="http://upx.sourceforge.net/"&gt;UPX&lt;/a&gt; and &lt;a href="http://www.matcode.com/mpress.htm"&gt;Mpress&lt;/a&gt;, both zip and 7zip can generate self-extracting executables. &lt;a href="http://en.wikipedia.org/wiki/Cabinet_(file_format)"&gt;Microsoft CAB&lt;/a&gt; also performs very well (See &lt;a href="http://lipidity.com/software/trimmit/"&gt;trimmit for Mac&lt;/a&gt;). But the state-of-the-art in self-extracting executable compressors for small programs are &lt;a href="http://www.crinkler.net/"&gt;Crinkler&lt;/a&gt; and &lt;a href="http://www.farbrausch.de/~fg/kkrunchy/"&gt;kkrunchy&lt;/a&gt; for &amp;lt; 4kb and &amp;lt; 128kb programs respectively. (A good resource for various tools is available at &lt;a href="http://in4k.untergrund.net/index.php?title=Exe_Tweakers_and_Linkers"&gt;in4k&lt;/a&gt;)  &lt;br /&gt;&lt;br /&gt;These compressors use a standard compression algorithm but also transform the input to a more compressible format. The most common transform algorithm is the &lt;a href="http://en.wikipedia.org/wiki/Burrows%E2%80%93Wheeler_transform"&gt;Burros Wheeler Transform (BWT)&lt;/a&gt;, this attempts to re-order data so that similar codes are close to each other - increasing the ability for the data to be compressed.&lt;br /&gt;&lt;br /&gt;For executable compression patterns in the instructions stream can be leveraged to increase the compression ratio. For example, instructions often address similar areas of memory, simple delta-encoding of the address values can typically greatly increase the compression ratio.&lt;br /&gt;&lt;br /&gt;Recently, both kkrunchy and Crinkler were described in detail. The &lt;a href="http://fgiesen.wordpress.com/2011/01/24/x86-code-compression-in-kkrunchy/"&gt;author of kkrunchy Fabian "ryg" Giesen wrote a great blog post describing how kkrunchy works&lt;/a&gt;. Since kkrunchy works with larger file sizes some more intelligent tricks can be applied. &lt;a href="http://code4k.blogspot.com/2010/12/crinkler-secrets-4k-intro-executable.html"&gt;Alexandre Mutel decomposed the Crinkler compressor in his blog post&lt;/a&gt; and posted some fabulous pictures of before-vs-after entropy of a compressed executable.    Unfortunately, both of these programs are targeted at Windows PE files, and so don't work for other platforms (See &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc301808.aspx"&gt;here&lt;/a&gt;, &lt;a href="http://api.farmanager.com/en/articles/bonus/msdnmag-issues-01-01-hood-default.aspx.html"&gt;here&lt;/a&gt;, &lt;a href="http://www.phreedom.org/solar/code/tinype/"&gt;here&lt;/a&gt; and &lt;a href="http://keyj.s2000.ws/?p=29"&gt;here&lt;/a&gt; for tips on PE).&lt;br /&gt;&lt;br /&gt;The usual approach to exe compression on linux/osx is just to do the modern-day version of com/cab dropping and compress your program with gzip and have a script extract and execute the program. This lacks a bit of flare, but works. Articles describing elf and mach-o are available by &lt;a href="http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html"&gt;Brian Raiter&lt;/a&gt; and &lt;a href="http://osxbook.com/blog/2009/03/15/crafting-a-tiny-mach-o-executable/"&gt;Amit Singh&lt;/a&gt; respectively, but unfortunately they are a little out of date.  &lt;br /&gt;&lt;br /&gt;A few tools have been written for linux and osx including the &lt;a href="http://www.alrj.org/projects/bold/"&gt;byte-optimized linker (x86/64)&lt;/a&gt; and &lt;a href="http://parapete.untergrund.net/bdle/"&gt;obj stripping&lt;/a&gt; for linux, and &lt;a href="http://www.pouet.net/prod.php?which=29185"&gt;iPakk&lt;/a&gt; and &lt;a href="http://www.pouet.net/prod.php?which=51324"&gt;muncho&lt;/a&gt; for OSX (again, a bit dated). An older &lt;a href="http://www.muppetlabs.com/~breadbox/software/elfkickers.html"&gt;elf stripper&lt;/a&gt; is  also around, and &lt;a href="http://users.utu.fi/tmwire/linux4k.html"&gt;Timo Wiren&lt;/a&gt; gives a good overview too. Unfortunately, &lt;a href="http://www.snisit.com/articles/mac-os-x-miniature-menagerie/"&gt;a similar page on OSX is no longer available online&lt;/a&gt; (maybe one day).  All in all, I've still found your best bet on a platform other than Windows is just to follow Timo Wiren's first step of advice and do a simple dropper: &lt;br /&gt;&lt;ol&gt;&lt;li&gt;Write your program, and compile it: g++ helloworld.cpp&lt;br /&gt;&lt;pre&gt;#include &lt;stdio.h&gt;&lt;br /&gt;&lt;br /&gt;int main() {&lt;br /&gt;printf("hello world!\n");&lt;br /&gt;return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/stdio.h&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Optional: Strip it &lt;pre&gt;strip a.out&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Compress it: &lt;pre&gt;gzip a.out&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Create the unpack script (unpack.header):&lt;br /&gt;&lt;pre&gt;a=/tmp/I;tail -n+2 $0|zcat&amp;gt;$a;chmod +x $a;$a;rm $a; exit&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Combine the script and zip into a final executable:&lt;br /&gt;&lt;pre&gt;cat unpack.header a.out.gz &amp;gt; program&lt;br /&gt;chmod +x program&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Enjoy! &lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;My a.out went from 8768 to 1153 bytes. Nice. (Using strip saves me 160 bytes on the original and 136 bytes on the final, but I'm sure you can save more by being clever about use of the gcc crt, &lt;a href="http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/i386-and-x86_002d64-Options.html"&gt;gcc flags&lt;/a&gt; and throwing a few tools at this process).&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-5357660253585804610?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/5357660253585804610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=5357660253585804610' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5357660253585804610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5357660253585804610'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/01/executable-compression.html' title='Executable compression'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/TT-g2MOrTlI/AAAAAAAAAWg/syKArgqcQCE/s72-c/compressdata.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-4676386670993379870</id><published>2011-01-11T19:33:00.017+08:00</published><updated>2011-01-12T20:10:55.783+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='raytracing'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><title type='text'>Tunnel effect explained in WebGL</title><content type='html'>&lt;script id="shader-vs" type="x-shader/x-vertex"&gt;//===================================================================================//Vertex Shader//===================================================================================  attribute vec3 aVertexPosition;  void main(void) {    gl_Position = vec4(aVertexPosition, 1.0);  }&lt;/script&gt;&lt;br /&gt;&lt;script id="shader-fs-tunnel" type="x-shader/x-fragment"&gt;//Script by Adrian Boeing//www.adrianboeing.com#ifdef GL_ESprecision highp float;#endifuniform vec2 resolution;uniform float time;uniform sampler2D tex;void main(void){    vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;    vec2 uv;       float a = atan(p.y,p.x);    float r = sqrt(dot(p,p));    uv.x = .15*time+.1/r;    uv.y = .1*time + a/(3.1416);    vec3 col =  texture2D(tex,uv).xyz;    gl_FragColor = vec4(col*r,1.0);}&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;//===================================================================================//Javascript code for setting up WebGL//===================================================================================  var canvas;  var startTime;   var gl;  var squareVertexPositionBuffer;  var shaderProgram;  var neheTexture;  function initGL(canvas) {    try {      gl = canvas.getContext("experimental-webgl");      gl.viewportWidth = canvas.width;      gl.viewportHeight = canvas.height;    } catch(e) {    }    if (!gl) {      alert("Could not initialise WebGL!");    }    startTime = (new Date()).getTime();  }  function getShader(gl, id) {    var shaderScript = document.getElementById(id);    if (!shaderScript) {      return null;    }    var str = "";    var k = shaderScript.firstChild;    while (k) {      if (k.nodeType == 3) {        str += k.textContent;      }      k = k.nextSibling;    }    var shader;    if (shaderScript.type == "x-shader/x-fragment") {      shader = gl.createShader(gl.FRAGMENT_SHADER);    } else if (shaderScript.type == "x-shader/x-vertex") {      shader = gl.createShader(gl.VERTEX_SHADER);    } else {      return null;    }    gl.shaderSource(shader, str);    gl.compileShader(shader);    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {      alert(gl.getShaderInfoLog(shader));      return null;    }    return shader;  }  function initShadersTunnel() {    var fragmentShader = getShader(gl, "shader-fs-tunnel");    //var fragmentShader = getShader(gl, "simple-fs");    var vertexShader = getShader(gl, "shader-vs");    shaderProgram = gl.createProgram();    gl.attachShader(shaderProgram, vertexShader);    gl.attachShader(shaderProgram, fragmentShader);    gl.linkProgram(shaderProgram);    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {      alert("Could not initialise shaders");    }    gl.useProgram(shaderProgram);    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);    shaderProgram.pResolutionUniform = gl.getUniformLocation(shaderProgram, "resolution");    shaderProgram.pTimeUniform = gl.getUniformLocation(shaderProgram, "time");  }  function setUniformsTunnel() {     gl.activeTexture(gl.TEXTURE0);    gl.bindTexture(gl.TEXTURE_2D, neheTexture);    gl.uniform1i(shaderProgram.samplerUniform, 0);      gl.uniform2f(shaderProgram.pResolutionUniform, canvas.width, canvas.height);    var time = (new Date()).getTime();    gl.uniform1f(shaderProgram.pTimeUniform, (time - startTime) / 1000.0);  }  function initBuffers() {    squareVertexPositionBuffer = gl.createBuffer();    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    vertices = [         1.0,  1.0,  0.0,        -1.0,  1.0,  0.0,         1.0, -1.0,  0.0,        -1.0, -1.0,  0.0    ];    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);    squareVertexPositionBuffer.itemSize = 3;    squareVertexPositionBuffer.numItems = 4;  }  function onWindowResize( event ) {    canvas.width = window.innerWidth;    canvas.height = window.innerHeight;    gl.viewport( 0, 0, canvas.width, canvas.height );  }    function handleLoadedTexture(texture) {    gl.bindTexture(gl.TEXTURE_2D, texture);    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);    gl.bindTexture(gl.TEXTURE_2D, null);  }   function initTexture() {    neheTexture = gl.createTexture();    neheTexture.image = new Image();    neheTexture.image.onload = function() {      handleLoadedTexture(neheTexture)    }    neheTexture.image.src = "http://www.iquilezles.org/apps/shadertoy/presets/tex2.jpg";   }      function drawScene() {    //gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);    gl.clear(gl.COLOR_BUFFER_BIT);    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);    setUniformsTunnel();    gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);  }  function webGLStartTunnel() {    canvas = document.getElementById("my-canvas-tunnel");    initGL(canvas);    initShadersTunnel()    initBuffers();    initTexture();    gl.clearColor(0.0, 0.0, 0.0, 1.0);    gl.disable(gl.DEPTH_TEST);    setInterval(drawScene, 16);  }  &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The tunnel effect builds on the circle equation we covered in the introductory XOR bitplasma. However, this time we need to add a two more concepts. First, we need to calculate the angle of each point on the screen, relative to the origin (center of screen). To find this we can use the properties of right-angle triangles, namely the &lt;a href="http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine.2C_and_tangent"&gt;tangent function (tan)&lt;/a&gt;. That is, the tangent of the angle is equal to opposite over adjacent. &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TS2TYR3yX2I/AAAAAAAAAWI/yGICZeYqJbo/s1600/tan.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TS2TYR3yX2I/AAAAAAAAAWI/yGICZeYqJbo/s1600/tan.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TS2T6SEwjNI/AAAAAAAAAWM/-dUv3VU8c84/s1600/tunnelgradient-angle.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="73" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TS2T6SEwjNI/AAAAAAAAAWM/-dUv3VU8c84/s200/tunnelgradient-angle.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Visualization of the angle for each pixel&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;By plugging in our pixel x/y coordinates we get a range from zero to pi of angles. Dividing by pi gives us a range from zero to one.  In code this is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;float a = atan(p.y,p.x);&lt;br /&gt;result =  a/(3.1416);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/TS2UVjBJPnI/AAAAAAAAAWQ/kklmE5w_Kdo/s1600/tunneldepth.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="150" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TS2UVjBJPnI/AAAAAAAAAWQ/kklmE5w_Kdo/s200/tunneldepth.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Tunnel depth&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Second, we need to find the "depth" of each point in the tunnel. Luckily this is easy to do, as projecting a 3d point to a 2d viewer is just a "divide by z" operation (objects that are further away appear smaller than objects that are closer - a nicer explanation will follow in future posts). So we can just generate a gradient of circles which we can treat as the distance from the viewer (our "z" value) and invert this (ie: 1/z).&lt;br /&gt;&lt;br /&gt;Finally to get a good effect we need to apply a &lt;a href="http://en.wikipedia.org/wiki/Texture_mapping"&gt;texture map&lt;/a&gt;. So combining the two coordinates we use the angular coordinate for the "v" coordinate and the depth coordinate as out "u" value.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TS2VPdXcvxI/AAAAAAAAAWU/Tz-hkCD8_do/s1600/texturetunnel.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="236" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TS2VPdXcvxI/AAAAAAAAAWU/Tz-hkCD8_do/s320/texturetunnel.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;So the complete code for our tunnel-shader is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;uniform vec2 resolution;&lt;br /&gt;uniform float time;&lt;br /&gt;uniform sampler2D tex;&lt;br /&gt;&lt;br /&gt;void main(void)&lt;br /&gt;{&lt;br /&gt;vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;&lt;br /&gt;vec2 uv;&lt;br /&gt;&lt;br /&gt;float a = atan(p.y,p.x);&lt;br /&gt;float r = sqrt(dot(p,p));&lt;br /&gt;&lt;br /&gt;uv.x = 0.1/r;&lt;br /&gt;uv.y = a/(3.1416);&lt;br /&gt;&lt;br /&gt;vec3 col =  texture2D(tex,uv).xyz;&lt;br /&gt;&lt;br /&gt;gl_FragColor = vec4(col,1.0);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;You can see the result below! (You will need a WebGL enabled browser)&lt;br /&gt;&lt;form&gt;&lt;input onclick="webGLStartTunnel()" type="button" value="Click me!" /&gt; &lt;/form&gt;&lt;canvas width="400" height="300" id="my-canvas-tunnel" &gt; Your browser doesn't appear to support the HTML5 &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element. &lt;/canvas&gt;&lt;br /&gt;&lt;br /&gt;As a small extension to this we can progressively change the power of the square function in the circle equation to generate a less and less round "curve", progressively changing the circular tunnel into a square tunnel.&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TS2VYLQ9dMI/AAAAAAAAAWY/EUAyyFQ6ofo/s1600/squares.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="158" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TS2VYLQ9dMI/AAAAAAAAAWY/EUAyyFQ6ofo/s200/squares.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Graph of increasing squares&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;So starting from:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;float power = 1.0;&lt;br /&gt;float r = pow( pow(p.x*p.x,power) + pow(p.y*p.y,power), 1.0/(2*power) );&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;We can slowly increase the power until we get a square-like tunnel. The image shows the effect of increasing the power term, the final bottom right two images show the contrast between the round and square-like tunnels.&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/_nHcDA3NyAms/TS2V2WTbpSI/AAAAAAAAAWc/CXsTed7-mOo/s1600/tunnel-small.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TS2V2WTbpSI/AAAAAAAAAWc/CXsTed7-mOo/s640/tunnel-small.jpg" width="640" /&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/17188375-4676386670993379870?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/4676386670993379870/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=4676386670993379870' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/4676386670993379870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/4676386670993379870'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/01/webgl-tunnel-effect-explained.html' title='Tunnel effect explained in WebGL'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_nHcDA3NyAms/TS2TYR3yX2I/AAAAAAAAAWI/yGICZeYqJbo/s72-c/tan.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-3824023823737822134</id><published>2011-01-09T12:57:00.037+08:00</published><updated>2011-01-10T22:49:53.354+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='demoscene'/><title type='text'>XOR Demoeffect in WebGL</title><content type='html'>&lt;script id="shader-vs" type="x-shader/x-vertex"&gt;//===================================================================================//Vertex Shader//===================================================================================  attribute vec3 aVertexPosition;  void main(void) {    gl_Position = vec4(aVertexPosition, 1.0);  }&lt;/script&gt;&lt;br /&gt;&lt;script id="shader-fs" type="x-shader/x-fragment"&gt;//Script by Adrian Boeing//www.adrianboeing.com#ifdef GL_ESprecision highp float;#endifuniform float time;uniform vec2 resolution;void main(void){    vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;    float t = time*0.5;    vec2 offset1 = vec2(0.5*cos(5.0*t),0.5*sin(3.0*t));    vec2 offset2 = vec2(0.6*sin(3.0*t),0.4*cos(2.0*t));    float radius1 = sqrt(dot(p-offset1,p-offset1));    float radius2 = sqrt(dot(p-offset2,p-offset2));            bool toggle1 = mod(radius1,0.2)&gt;0.1;    bool toggle2 = mod(radius2,0.2)&gt;0.1;    //xor via if statements    float col = 0.0;    if (toggle1) col = 1.0;        if (toggle2) col = 1.0;    if ((toggle1) &amp;&amp; (toggle2)) col = 0.0;    gl_FragColor = vec4(col,col,col,1.0);}&lt;/script&gt;&lt;br /&gt;&lt;script id="simple-fs" type="x-shader/x-fragment"&gt;//===================================================================================//Fragment Shader//===================================================================================precision highp float;uniform vec2 resolution;uniform float time;void main(void){    gl_FragColor = vec4(gl_FragCoord.x / resolution.x, gl_FragCoord.y / resolution.y, time - floor(time), 1.0);}&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;//===================================================================================//Javascript code for setting up WebGL//===================================================================================  var canvas;  var startTime;   var gl;  var squareVertexPositionBuffer;  var shaderProgram;  function initGL(canvas) {    try {      gl = canvas.getContext("experimental-webgl");      gl.viewportWidth = canvas.width;      gl.viewportHeight = canvas.height;    } catch(e) {    }    if (!gl) {      alert("Could not initialise WebGL!");    }    startTime = (new Date()).getTime();  }  function getShader(gl, id) {    var shaderScript = document.getElementById(id);    if (!shaderScript) {      return null;    }    var str = "";    var k = shaderScript.firstChild;    while (k) {      if (k.nodeType == 3) {        str += k.textContent;      }      k = k.nextSibling;    }    var shader;    if (shaderScript.type == "x-shader/x-fragment") {      shader = gl.createShader(gl.FRAGMENT_SHADER);    } else if (shaderScript.type == "x-shader/x-vertex") {      shader = gl.createShader(gl.VERTEX_SHADER);    } else {      return null;    }    gl.shaderSource(shader, str);    gl.compileShader(shader);    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {      alert(gl.getShaderInfoLog(shader));      return null;    }    return shader;  }  function initShaders() {    var fragmentShader = getShader(gl, "shader-fs");    //var fragmentShader = getShader(gl, "simple-fs");    var vertexShader = getShader(gl, "shader-vs");    shaderProgram = gl.createProgram();    gl.attachShader(shaderProgram, vertexShader);    gl.attachShader(shaderProgram, fragmentShader);    gl.linkProgram(shaderProgram);    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {      alert("Could not initialise shaders");    }    gl.useProgram(shaderProgram);    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);    shaderProgram.pResolutionUniform = gl.getUniformLocation(shaderProgram, "resolution");    shaderProgram.pTimeUniform = gl.getUniformLocation(shaderProgram, "time");  }  function setUniforms() {    gl.uniform2f(shaderProgram.pResolutionUniform, canvas.width, canvas.height);    var time = (new Date()).getTime();    gl.uniform1f(shaderProgram.pTimeUniform, (time - startTime) / 1000.0);  }  function initBuffers() {    squareVertexPositionBuffer = gl.createBuffer();    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    vertices = [         1.0,  1.0,  0.0,        -1.0,  1.0,  0.0,         1.0, -1.0,  0.0,        -1.0, -1.0,  0.0    ];    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);    squareVertexPositionBuffer.itemSize = 3;    squareVertexPositionBuffer.numItems = 4;  }  function onWindowResize( event ) {    canvas.width = window.innerWidth;    canvas.height = window.innerHeight;    gl.viewport( 0, 0, canvas.width, canvas.height );  }  function drawScene() {    //gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);    gl.clear(gl.COLOR_BUFFER_BIT);    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);    setUniforms();    gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);  }  function webGLStart() {    canvas = document.getElementById("my-canvas");    initGL(canvas);    initShaders()    initBuffers();    gl.clearColor(0.0, 0.0, 0.0, 1.0);    gl.disable(gl.DEPTH_TEST);    setInterval(drawScene, 16);  }&lt;/script&gt;&lt;br /&gt;I wanted to do a series on a set of demoeffects, inspired by &lt;a href="http://www.iquilezles.org/apps/shadertoy/"&gt;Shader Toy&lt;/a&gt; (and Denthor!). The majority of the shader toy effects  are either raytraced, or polar/circle-based. So I thought I would begin with polar/circles and work my way from there. Most of the effects are based on a number of "oldschool" &lt;a href="http://en.wikipedia.org/wiki/Demoscene"&gt;democoder&lt;/a&gt; tricks that are easy to understand once you have the background knowledge.&lt;br /&gt;&lt;br /&gt;I won't be covering the basics behind writing shaders, but I might do so at a later point.&lt;br /&gt;&lt;br /&gt;All of iq's shaders are rendered using a pixel shader (or fragment shader in OpenGL talk).  The first step is to calculate the position of the pixel on the screen (or canvas in case of WebGL) normalised from -1 to 1. In a picture this is:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TSsasEe7m0I/AAAAAAAAAVs/507P20um1xg/s1600/xyaxis.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="296" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TSsasEe7m0I/AAAAAAAAAVs/507P20um1xg/s320/xyaxis.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;To visualise this in the shader we could write:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;void main(void)&lt;br /&gt;{&lt;br /&gt;vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;&lt;br /&gt;gl_FragColor = vec4(p.x,p.y,0.0,1.0);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Now each horizontal value will get an increasing value of red, and each vertical value will get an increasing value of green (we are using the RGBA color space)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TSsa1-jedfI/AAAAAAAAAVw/YoO4tS-rZaE/s1600/redgradient.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="146" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TSsa1-jedfI/AAAAAAAAAVw/YoO4tS-rZaE/s200/redgradient.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/TSsbQZR6F9I/AAAAAAAAAV8/J4wSco8prhw/s1600/x2y2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TSsbQZR6F9I/AAAAAAAAAV8/J4wSco8prhw/s1600/x2y2.png" /&gt;&lt;/a&gt;We can use the &lt;a href="http://en.wikipedia.org/wiki/Circle#Cartesian_coordinates"&gt;cartesian equation of a circle&lt;/a&gt; to generate a gradient of circles.&lt;br /&gt;&lt;br /&gt;Again, to visualise this in the shader we could write: &lt;br /&gt;&lt;code&gt;&lt;br /&gt;void main(void)&lt;br /&gt;{&lt;br /&gt;vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;&lt;br /&gt;float radius = sqrt(p.x*p.x + p.y*p.y);   &lt;br /&gt;gl_FragColor = vec4(radius,0.0,0.0,1.0);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;If we want to generate concentric circles we could set a boolean value on or off depending on a &lt;a href="http://en.wikipedia.org/wiki/Modulo_operation"&gt;modulo operation&lt;/a&gt;. If we take the modulo of a value and then test whether it is above half-way then we can generate an on-off pulse. For example, if we get a value ranging from 0 to 1, module 0.1, we can generate a on/off pulse by testing if it is greater than 0.05.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TSsa9CRgftI/AAAAAAAAAV0/2n-Wwx3Nhgk/s1600/modulo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="153" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TSsa9CRgftI/AAAAAAAAAV0/2n-Wwx3Nhgk/s200/modulo.png" width="200" /&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/_nHcDA3NyAms/TSsbFY-sRZI/AAAAAAAAAV4/SjU58OPHaVM/s1600/redcircles.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="146" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TSsbFY-sRZI/AAAAAAAAAV4/SjU58OPHaVM/s200/redcircles.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;In shader code this would be:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;void main(void)&lt;br /&gt;{&lt;br /&gt;vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;&lt;br /&gt;&lt;br /&gt;float radius = sqrt(p.x*p.x + p.y*p.y);&lt;br /&gt;float modulo = mod(radius,0.1);&lt;br /&gt;bool toggle = false;&lt;br /&gt;if (modulo &amp;gt; 0.05) toggle = true;&lt;br /&gt;if (toggle)&lt;br /&gt;gl_FragColor = vec4(1.0,0.0,0.0,1.0);&lt;br /&gt;else&lt;br /&gt;gl_FragColor = vec4(0.0,0.0,0.0,1.0);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This is a bit long-handed, we can shorten this by directly setting the toggle value, and using the &lt;a href="http://en.wikipedia.org/wiki/Dot_product"&gt;dot product&lt;/a&gt; to perform the square operations. &lt;br /&gt;ie:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;float radius = sqrt(dot(p,p));&lt;br /&gt;bool toggle = mod(radius,0.1)&amp;gt;0.05;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Great! Now we have all the background knowledge we need to make our first interesting effect. This will be based on the &lt;a href="http://en.wikipedia.org/wiki/Exclusive_or"&gt;XOR operation&lt;/a&gt;:&lt;br /&gt;&lt;table style="text-align: center;"&gt;&lt;caption&gt;XOR Truth Table&lt;/caption&gt;  &lt;tbody&gt;&lt;tr&gt;  &lt;th colspan="2"&gt;Input&lt;/th&gt;  &lt;th rowspan="2"&gt;Output&lt;/th&gt;  &lt;/tr&gt;&lt;tr&gt;  &lt;th&gt;A&lt;/th&gt;  &lt;th&gt;B&lt;/th&gt;  &lt;/tr&gt;&lt;tr&gt;  &lt;td&gt;0&lt;/td&gt;  &lt;td&gt;0&lt;/td&gt;  &lt;td&gt;0&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;  &lt;td&gt;0&lt;/td&gt;  &lt;td&gt;1&lt;/td&gt;  &lt;td&gt;1&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;  &lt;td&gt;1&lt;/td&gt;  &lt;td&gt;0&lt;/td&gt;  &lt;td&gt;1&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;  &lt;td&gt;1&lt;/td&gt;  &lt;td&gt;1&lt;/td&gt;  &lt;td&gt;0&lt;/td&gt;  &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TSsbajXX2PI/AAAAAAAAAWA/Dsvm80jCf9g/s1600/twocircles.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="144" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TSsbajXX2PI/AAAAAAAAAWA/Dsvm80jCf9g/s200/twocircles.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;First, lets generate two different circles. &lt;br /&gt;&lt;code&gt;&lt;br /&gt;void main(void)&lt;br /&gt;{&lt;br /&gt;vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;&lt;br /&gt;&lt;br /&gt;vec2 offset2 = vec2(0.3,0.3);&lt;br /&gt;&lt;br /&gt;float radius1 = sqrt(dot(p,p));&lt;br /&gt;float radius2 = sqrt(dot(p-offset2,p-offset2));&lt;br /&gt;&lt;br /&gt;bool toggle1 = mod(radius1,0.1)&amp;gt;0.05;&lt;br /&gt;bool toggle2 = mod(radius2,0.1)&amp;gt;0.05;&lt;br /&gt;&lt;br /&gt;gl_FragColor = vec4(toggle1,toggle2,0.0,1.0);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&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/_nHcDA3NyAms/TSscHBTQj4I/AAAAAAAAAWE/aT8hx-mjLv8/s1600/xoreffect.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="141" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TSscHBTQj4I/AAAAAAAAAWE/aT8hx-mjLv8/s200/xoreffect.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;Wonderfull! Now if we add in the XOR truth table:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;//xor via if statements&lt;br /&gt;float col = 0.0;&lt;br /&gt;if (toggle1) col = 1.0;    &lt;br /&gt;if (toggle2) col = 1.0;&lt;br /&gt;if ((toggle1) &amp;amp;&amp;amp; (toggle2)) col = 0.0;&lt;br /&gt;&lt;br /&gt;gl_FragColor = vec4(col,0.0,0.0,1.0);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And we get a wonderful overlapping pattern.&lt;br /&gt;&lt;br /&gt;Add in a bit of animation and we have our first demoeffect! Click the button below in a &lt;a href="http://www.khronos.org/webgl/wiki/Getting_a_WebGL_Implementation"&gt;WebGL enabled browser (Firefox, Chrome, Safari)&lt;/a&gt;. (view source for full code)&lt;br /&gt;&lt;br /&gt;&lt;form&gt;&lt;input onclick="webGLStart()" type="button" value="Click me!" /&gt; &lt;/form&gt;&lt;canvas height="300" id="my-canvas" width="400"&gt; Your browser doesn't appear to support the HTML5 &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element. &lt;/canvas&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-3824023823737822134?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/3824023823737822134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=3824023823737822134' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3824023823737822134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3824023823737822134'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/01/xor-demoeffect-in-webgl.html' title='XOR Demoeffect in WebGL'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_nHcDA3NyAms/TSsasEe7m0I/AAAAAAAAAVs/507P20um1xg/s72-c/xyaxis.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-3565032569337460388</id><published>2011-01-07T20:13:00.081+08:00</published><updated>2011-01-08T22:24:28.511+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='computers'/><category scheme='http://www.blogger.com/atom/ns#' term='GPGPU'/><title type='text'>Future CPU/GPU architectures and OpenCL</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TShzITKwM7I/AAAAAAAAAVk/nIGg67hwtUg/s1600/sandybridge.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="172" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TShzITKwM7I/AAAAAAAAAVk/nIGg67hwtUg/s320/sandybridge.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;For a while x86 CPUs were just aimed at getting faster, more and more ticks. Then, there was a shift from faster to more efficient (in terms of power used / heat generated vs. performance) in the Pentium 3/4 era. Then, another shift towards multiple cores. Now, the next shift has occurred: CPU and GPU fusion. (Despite AMD talking about it for longer than I can recall. I think I was talking to an AMD VP shortly before they purchased ATI about how GPU and CPU fusion was the future.) &lt;br /&gt;&lt;br /&gt;Recently &lt;a href="http://www.geeks3d.com/20110103/intel-sandy-bridge-processors-cpugpu-launched/"&gt;Intel released Sandy Bridge&lt;/a&gt; their CPU/GPU processor, and &lt;a href="http://sites.amd.com/us/fusion/apu/Pages/fusion.aspx"&gt;AMD's fusion APU's&lt;/a&gt; have been around. Interestingly, both are targeted at laptops (the bulk of the market), and still expect discrete GPU's for high-end performance. The fusion is just a bit of a bonus.&lt;br /&gt;&lt;br /&gt;Interestingly all those &lt;a href="http://www.theinquirer.net/inquirer/news/1050874/nvidia-trying-x86-chip"&gt;2009 rumours about nVidia building an x86 chip&lt;/a&gt; turned out to be wrong, with the real product being far more interesting. An nVidia fusion product of an &lt;a href="http://blogs.nvidia.com/2011/01/project-denver-processor-to-usher-in-new-era-of-computing/"&gt;ARM CPU with nVidia GPU's&lt;/a&gt;. This might prove to be a very interesting result considering the amount of effort being put into improving the ARM architecture and the power usage concerns in both smartphones/tablets and supercomputing. With the &lt;a href="http://www.microsoft.com/Presspass/Features/2011/jan11/01-05SinofskySOC.mspx"&gt;next version of windows running on ARM&lt;/a&gt; there will certainly be interesting times ahead.&lt;br /&gt;&lt;br /&gt;Intel/AMD aren't standing still on the CPU front and are pushing ahead with &lt;a href="http://software.intel.com/en-us/avx/"&gt;AVX&lt;/a&gt; but the real interesting part is that OpenCL is being pushed across the board. Recent publications from the &lt;a href="http://www.many-core.group.cam.ac.uk/ukgpucc2/programme.shtml"&gt;UK GPU computing conference&lt;/a&gt; demonstrate that ARM are pushing OpenCL as their platform of choice (for both CPU and their Mali GPU, it is Clang/LLVM based), and AMD and Intel have been strong supporters of OpenCL too. Did you know &lt;a href="http://opencl.snu.ac.kr/"&gt;Samsung supports OpenCL&lt;/a&gt; too? &lt;br /&gt;&lt;br /&gt;It would seem that OpenCL has a very strong support base, and is likely the platform of choice for developers on &lt;a href="http://sa10.idav.ucdavis.edu/"&gt;Intel, AMD, ARM, Apple, IBM&lt;/a&gt;, etc. What hope does CUDA stand? It seems nVidia will eventually be forced to drop CUDA, or invest heavily into CPU-based CUDA &lt;a href="http://code.google.com/p/gpuocelot/"&gt;(Hello Ocelot!)&lt;/a&gt; or OpenCL translation. Eventually people will tire of writing and re-writing CUDA programs as they swap between platforms. &lt;br /&gt;&lt;br /&gt;Envision the not-so-far future where you have a workstation with multiple CPU/GPU fusion cores [non-CUDA], and a discrete fusion GPU (GPU [CUDA]/ARM [non-CUDA] core) - are you really willing to write a specific CUDA routine for just the nVidia GPU, or are you more likely to try a less optimal OpenCL routine that will then also then run on the CPU, CPU SIMD, CPU/GPU fusion and ARM cores? &lt;br /&gt;&lt;br /&gt;It seems that the argument being put forward by nVidia to write everything in CUDA for optimal performance will not hold as you will gain more from all the other devices helping out in the computation compared to the loss from using OpenCL over CUDA.&lt;br /&gt;&lt;br /&gt;Of course there are other choices out there such as Accelerator and RapidMind.&lt;br /&gt;&lt;br /&gt;The UK conference reveals Microsoft's GPGPU language "&lt;a href="http://research.microsoft.com/en-us/projects/accelerator/"&gt;Accelerator&lt;/a&gt;" has made progress, and now is no longer only GPU limited (it now supports SSE3 on modern CPU's). I'm still not aware of anyone using this for anything practical though, which seems to be a bit of a shame. And ever since Intel bought RapidMind (now &lt;a href="http://software.intel.com/en-us/articles/intel-array-building-blocks/"&gt;Array Building Blocks&lt;/a&gt;) the tech became very Intel-specific. So neither of those choices sound too promising.&lt;br /&gt;&lt;br /&gt;It will be interesting to see what nVidia decide to do with CUDA, how developers will adjust to fusion CPU / GPUs and what higher-level language (or language extension?) will become de-facto in the future. Stay tuned..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-3565032569337460388?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/3565032569337460388/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=3565032569337460388' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3565032569337460388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3565032569337460388'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/01/future-cpugpu-architectures-and-opencl.html' title='Future CPU/GPU architectures and OpenCL'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nHcDA3NyAms/TShzITKwM7I/AAAAAAAAAVk/nIGg67hwtUg/s72-c/sandybridge.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-903485488851681768</id><published>2011-01-02T00:07:00.000+08:00</published><updated>2011-01-02T00:07:03.305+08:00</updated><title type='text'>2010 Summary</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TR9RFBPQGNI/AAAAAAAAAVg/yO9c8A8_zIs/s1600/2011.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="129" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TR9RFBPQGNI/AAAAAAAAAVg/yO9c8A8_zIs/s320/2011.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Looking back, 2010 was a big year. My life was dominated by three factors:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Our entry into &lt;a href="http://www.dsto.defence.gov.au/MAGIC2010/"&gt;MAGIC 2010&lt;/a&gt;, with the &lt;a href="http://www.wambot.org/"&gt;WAMbot autonomous robots&lt;/a&gt;. Our team managed to place &lt;a href="http://adrianboeing.blogspot.com/2010/11/team-magicianwambot-takes-4th-place.html"&gt;fourth out of 23 international competitors&lt;/a&gt; and placed best in Australia (and Asia!). Unfortunately, due to the competitive nature of the event, I didn't blog everything I did or any of the great stuff our team put together. Hopefully I will be able to catch up on that in 2011. Popular posts on this area for 2010 were all on filtering, including &lt;a href="http://adrianboeing.blogspot.com/2010/03/alpha-beta-filters.html"&gt;alpha-beta filters&lt;/a&gt;, and the more advanced &lt;a href="http://adrianboeing.blogspot.com/2010/05/kalman-filters.html"&gt;Kalman filters (part1)&lt;/a&gt; and&lt;br /&gt;&lt;a href="http://adrianboeing.blogspot.com/2010/08/kalman-filters-part-2.html"&gt;Kalman filters (part2)&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Working at Transmin, including the commissioning of the now world-famous &lt;a href="http://www.youtube.com/watch?v=v1AJ_OBJUpY"&gt;Transmin Grapples (controlled by a wiimote)&lt;/a&gt; in the UK. Popular posts on this work were realting to the collision system &lt;a href="http://adrianboeing.blogspot.com/2010/10/convex-hull-generation-in-blender.html"&gt;convex hull generation&lt;/a&gt; and &lt;a href="http://adrianboeing.blogspot.com/2010/01/barycentric-coordinates.html"&gt;barycentric coordinates&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Getting married in Vac, Hungary!&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;A bit of a departure from 2009 which was mostly focused on GPGPU, fluid simulations, physics engines, and computer graphics. I still have a backlog of content to write about from my GPGPU work in 2009, but its starting to be less relevant as the GPGPU world pushes ahead, but I'm aiming to post more in 2011 than I managed in 2010. Should be a good year!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-903485488851681768?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/903485488851681768/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=903485488851681768' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/903485488851681768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/903485488851681768'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2011/01/2010-summary.html' title='2010 Summary'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nHcDA3NyAms/TR9RFBPQGNI/AAAAAAAAAVg/yO9c8A8_zIs/s72-c/2011.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-6523156460597521998</id><published>2010-12-29T20:50:00.000+08:00</published><updated>2010-12-29T20:50:17.699+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='raytracing'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='GPGPU'/><category scheme='http://www.blogger.com/atom/ns#' term='fluid'/><title type='text'>Catchup Post: Graphics</title><content type='html'>&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TRssndYfWBI/AAAAAAAAAVc/mWC_6m6fLTA/s1600/shadertoy.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="148" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TRssndYfWBI/AAAAAAAAAVc/mWC_6m6fLTA/s200/shadertoy.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="http://www.iquilezles.org/apps/shadertoy/"&gt;ShaderToy&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Another set of interesting links:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.iquilezles.org/apps/shadertoy/"&gt;Inigo Quilez's Demoscene Shader Toy&lt;/a&gt; is absolutely fantastic. It is like the modern day version of Grant Smith's (Denthor) Asphyxia Tutorials. Many demoscene effects in glsl shaders, including a whole bunch with raytracing and ambient occlusion, etc. You will need a webgl compatible browser (e.g. the new version of &lt;a href="http://www.google.com/landing/chrome/beta/"&gt;Chrome (v9 - currently beta)&lt;/a&gt;). With any luck I'll spend some time in future describing how each effect is achieved.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A &lt;a href="http://mandel.kex3.com/"&gt;web based mandelbrot fractal viewer&lt;/a&gt; with a google-maps interface.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A short explanation with some nice visual examples of how &lt;a href="http://udn.epicgames.com/Three/ProceduralBuildings.html"&gt;procedural buildings are generated in Unreal Engine 3&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Once you have built your city, you can use more &lt;a href="http://www.procedural.com/showcases/showcase/destroyed-city.html"&gt;procedural tools to destroy a city&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.andersriggelsen.dk/OpenGL/"&gt;Visual glBlendFunc tool&lt;/a&gt;, for helping you decide what blending you would like. (Additive glBlendFunc(GL_ONE,GL_ONE) and Screen glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_COLOR) are useful ones)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://colorschemedesigner.com/"&gt;Color Scheme Designer 3&lt;/a&gt; helps you pick good colors.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.romancortes.com/blog/how-i-did-the-1kb-christmas-tree/"&gt;An interesting one kilobyte javascript christmas tree&lt;/a&gt; with an explanation of how its done.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The &lt;a href="http://qoob.weebly.com/index.html"&gt;tiny 3d modeler Qoob&lt;/a&gt; has made great progress, and the library is now public. Should help with those 64kb intros/games.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://assimp.sourceforge.net/main_features_pp.html"&gt;Open Asset Import Library&lt;/a&gt; has made good progress and can now load a large number of 3d model formats.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The &lt;a href="http://www.gremedy.com/purchase.php"&gt; OpenGL / OpenCL gDEBugger is now free&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.amd.com/archive/gpu/tootle/Pages/default.aspx"&gt;AMD's triangle order optimization tool&lt;/a&gt; has had its final release.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.geeks3d.com/20101205/amd-opencl-presentations-sph-and-device-fission/"&gt;AMD OpenCL presentation on Smooth Particle Hydrodynamics&lt;/a&gt;. Now everybody is doing it... &lt;br /&gt;&lt;/li&gt;Farbraush's latest demo does SPH, but at a pretty low resolution for some reason. Still worth a watch:&lt;object width="560" height="340"&gt;&lt;param name="movie" value="http://www.youtube.com/v/2Vguvli1Y0k?fs=1&amp;amp;hl=en_US"&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/2Vguvli1Y0k?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"&gt;&lt;/embed&gt;&lt;/object&gt;And that's it for another month. &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-6523156460597521998?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/6523156460597521998/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=6523156460597521998' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6523156460597521998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6523156460597521998'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/12/catchup-post-graphics.html' title='Catchup Post: Graphics'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nHcDA3NyAms/TRssndYfWBI/AAAAAAAAAVc/mWC_6m6fLTA/s72-c/shadertoy.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-7347052287188897149</id><published>2010-12-24T17:21:00.000+08:00</published><updated>2010-12-24T17:21:05.225+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><title type='text'>Humble Bundle #2 - Great indy games - name your price!</title><content type='html'>&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TRRlZLGhh4I/AAAAAAAAAVU/36vuHs9bOqs/s1600/osmos.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TRRlZLGhh4I/AAAAAAAAAVU/36vuHs9bOqs/s1600/osmos.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt; &lt;a href="http://www.hemispheregames.com/osmos/"&gt;Osmos&lt;/a&gt; - Humble Bundle 2&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;The independent games &lt;a href="http://www.humblebundle.com/"&gt;humble bundle&lt;/a&gt; offer is back again, better than before. It is a pay-what-you-want offer for 5 indy games, all of which have support for Windows, Mac OSX and Linux. If you pay above the average, you get the previous humble-bundle pack of 6 games as well! A very good deal for whatever you want to pay! (Makes an excellent Christmas present!) Anyone studying games design or games programming should get these games to learn from them - what works, what doesn't? Braid is a fabulous example of teaching the player the game without needing to give them a tutorial, and many of these games are great examples of the scope you should aim for if you are making your own game.&lt;br /&gt;&lt;br /&gt;The games included are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://braid-game.com/"&gt;Braid&lt;/a&gt; - a side scrolling puzzle/adventure through time. Nicely designed gameplay.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Cortex Command - side scroller, not very impressive.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://machinarium.net/"&gt;Machinarium&lt;/a&gt; - a point and click adventure game, nice graphics, pretty decent.  &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.hemispheregames.com/osmos/"&gt;Osmos&lt;/a&gt; - an ambient physics-based "eating" game (you absorb smaller entities). Good gameplay and a great "programmer-game" (nice graphics). My pick of the lot. (only $10 separately)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Revenge of the Titans - a tower-defense (build towers that destroy enemies) game. Nothing special.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The other games are: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;World of Goo - a construction puzzle game. Lots of fun.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Aquaria - an underwater fantasy game.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Gish - a platform game.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Lugaru - 3D action adventure game.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Penumbrac - a FPS/adventure game.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Samorost 2 - a flash-based puzzle game.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;If you pay 10 USD to get them all, that works out to less than a dollar a game, and I guarantee you will find at least one game you think is worth $10 in the &lt;a href="http://www.humblebundle.com/"&gt;humble (cross-platform games) bundle&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-7347052287188897149?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/7347052287188897149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=7347052287188897149' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7347052287188897149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7347052287188897149'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/12/humble-bundle-2-great-indy-games-name.html' title='Humble Bundle #2 - Great indy games - name your price!'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nHcDA3NyAms/TRRlZLGhh4I/AAAAAAAAAVU/36vuHs9bOqs/s72-c/osmos.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-2882805442800345995</id><published>2010-12-23T23:51:00.001+08:00</published><updated>2012-01-12T21:52:48.978+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mining'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><title type='text'>Underground</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TRNujQWB6KI/AAAAAAAAAVM/NwanbmwJeHI/s1600/IMG_0329-small.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="141" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TRNujQWB6KI/AAAAAAAAAVM/NwanbmwJeHI/s200/IMG_0329-small.JPG" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;Few updates this month because I've been underground. And I don't mean I've joined some kind of strange sub-culture or gone in hiding, I mean literally 1.5km vertically underground to commission a &lt;a href="http://www.transmin.com.au/"&gt;Transmin automated Rockbreaker&lt;/a&gt; (there's not much internet down there!). A few things I learnt / experienced about hard-rock underground mines (most of which are very obvious):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Underground_mining_(hard_rock)#Bulk_mining_methods"&gt;Block caving&lt;/a&gt; is insane. The idea is to create an extraction level under the ore body, then continuously blast the ore into smaller rocks that can be processed, leaving a massive growing "sink" hole on the surface. You also need a very very very long conveyor belt.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The tunnels are quite large, as some very large vehicles need to drive through the mine.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;All the tunnels have a 'clean' look to them, largely thanks to the use of shotcrete (i.e. concrete reinforcement around the tunnel rock).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It takes 45 minutes to drive down to a depth of 1.5km&lt;br /&gt;&lt;/li&gt;&lt;li&gt;When driving, give way to larger vehicles, or vehicles with explosives.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Its difficult to move around quickly, you will easily break a sweat in no time.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Batteries weigh a lot when you need to carry them around on a belt all day&lt;br /&gt;&lt;/li&gt;&lt;li&gt;You use a lot more oxygen if you panic, or move around a lot&lt;br /&gt;&lt;/li&gt;&lt;li&gt;There is a complex system of ventilation channels with really really big fans providing all the air&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It is really easy to get lost in a large underground mine&lt;br /&gt;&lt;/li&gt;&lt;li&gt;There is an underground dining area. It is called the 'crib'. I don't know why.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;If anything bad happens, you don't have much of a chance, especially if you are not aware of all the intimate details of how the mine operates. (ie: haven't been there for more than a year)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Explosions are loud&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Ground movement is bad and very very loud&lt;br /&gt;&lt;/li&gt;&lt;li&gt;There is an awful lot of dust&lt;br /&gt;&lt;/li&gt;&lt;/ul&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://3.bp.blogspot.com/_nHcDA3NyAms/TRNvtqlXAxI/AAAAAAAAAVQ/i5p0gj75-h8/s1600/IMG_0339+crop-small.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TRNvtqlXAxI/AAAAAAAAAVQ/i5p0gj75-h8/s200/IMG_0339+crop-small.JPG" width="133" /&gt;&lt;/a&gt;&lt;/div&gt;All in all an interesting experience, but all the dust certainly didn't do any good for my eyes or my lungs. I've been coughing a lot even after being out of the mine for a week as the very fine dust just gets everywhere.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-2882805442800345995?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/2882805442800345995/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=2882805442800345995' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/2882805442800345995'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/2882805442800345995'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/12/underground.html' title='Underground'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nHcDA3NyAms/TRNujQWB6KI/AAAAAAAAAVM/NwanbmwJeHI/s72-c/IMG_0329-small.JPG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-7275967455589454014</id><published>2010-11-26T17:34:00.000+08:00</published><updated>2010-11-26T17:34:20.583+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><title type='text'>XV-11 LIDAR Hacked!</title><content type='html'>Congratulations to the team at &lt;a href="http://random-workshop.blogspot.com/2010/11/python-source-code.html"&gt;Random Workshop blog&lt;/a&gt;, Hash Salehi modified some code from Nicolas Saugnier to parse the LIDAR data in realtime!&lt;br /&gt;&lt;br /&gt;Movie follows:&lt;br /&gt;&lt;object width="560" height="340"&gt;&lt;param name="movie" value="http://www.youtube.com/v/tPBixFssIpU?fs=1&amp;amp;hl=en_US"&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/tPBixFssIpU?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;That didn't take long!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-7275967455589454014?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/7275967455589454014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=7275967455589454014' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7275967455589454014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7275967455589454014'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/11/xv-11-lidar-hacked.html' title='XV-11 LIDAR Hacked!'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-8654833173285821635</id><published>2010-11-25T09:21:00.001+08:00</published><updated>2010-11-25T09:21:00.324+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GPGPU'/><title type='text'>GPGPU catchup</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TO0z1b0QXOI/AAAAAAAAAVI/-Cy8e91vkX4/s1600/ge-gpu.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TO0z1b0QXOI/AAAAAAAAAVI/-Cy8e91vkX4/s1600/ge-gpu.png" /&gt;&lt;/a&gt;&lt;/div&gt;Another month, another catchup post on the world of GPU's. A few interesting things have happened:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.nvidia.com/object/research_summit_posters_2010.html"&gt;nVidia have released the posters from the 2010 Research Summit on GPU Technology&lt;/a&gt;, there are a number of absolutely fantastic posters in this collection - too many to list individually!&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.nvidia.com/object/cuda_3_2_downloads.html"&gt;CUDA 3.2&lt;/a&gt; has been released, with H.264, random number, and sparse matrix support, along with the usual smattering of improvements.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://software.intel.com/en-us/articles/intel-opencl-sdk/"&gt;Intel OpenCL&lt;/a&gt; has finally been publicly released as an alpha. Ofcourse it only targets the Streaming SIMD Extensions (SSE) for Intel CPU's. Still no word from IBM or ARM on their OpenCL implementations.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://aws.typepad.com/aws/2010/11/new-ec2-instance-type-the-cluster-gpu-instance.html"&gt;Amazon EC2 provides GPGPU&lt;/a&gt; capabilities now, and &lt;a href="http://blog.cyclecomputing.com/2010/11/a-couple-more-nails-in-the-coffin-of-the-private-compute-cluster-gpu-on-cloud.html"&gt;early benchmarks&lt;/a&gt; show that it performs relatively well.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.ge-ip.com/products/family/gpgpu"&gt;General Electric have released an embedded GPU platform&lt;/a&gt;. This looks great, I don't know why more people haven't mentioned this. GPU's are perfect for many of the processing problems we deal with for autonomous vehicles in interpreting vision, RADAR and LIDAR data.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.mathworks.com/help/toolbox/distcomp/rn/bsloyak-1.html#bsiqpvy-1"&gt;Matlabs Parallel Computing Toolbox&lt;/a&gt; has gained strong support for GPGPU's.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.streamcomputing.eu/blog"&gt;Vincent Hindriksen&lt;/a&gt; runs an interesting blog on stream computing trends.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Not sure if I've already mentioned this, but &lt;a href="http://aras-p.info/blog/2010/09/29/glsl-optimizer/?utm_source=feedburner&amp;amp;utm_medium=feed&amp;amp;utm_campaign=Feed%3A+LostInTheTriangles+%28Lost+in+the+triangles%29"&gt;Aras Pranckevičius&lt;/a&gt; implemented an interesting GLSL optimizer.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Finally &lt;a href="http://www.isislab.it/projects/behavert/"&gt;BehaveRT&lt;/a&gt; is a GPU based behavior (ie flocking) system that can control &amp;gt;30,000 agents at once. Check out the video below:&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;object height="390" width="640"&gt;&lt;param name="movie" value="http://www.youtube.com/v/eymho1qRqK4&amp;hl=it_IT&amp;feature=player_embedded&amp;version=3"&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/eymho1qRqK4&amp;hl=it_IT&amp;feature=player_embedded&amp;version=3" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="390"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-8654833173285821635?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/8654833173285821635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=8654833173285821635' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8654833173285821635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8654833173285821635'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/11/gpgpu-catchup.html' title='GPGPU catchup'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_nHcDA3NyAms/TO0z1b0QXOI/AAAAAAAAAVI/-Cy8e91vkX4/s72-c/ge-gpu.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-6648895799026322581</id><published>2010-11-24T13:42:00.001+08:00</published><updated>2010-11-24T23:53:08.834+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><title type='text'>Microsoft Kinect and other devices</title><content type='html'>The Microsoft Kinect is a very cheap 3d vision system that provides performance somewhere between stereo cameras and more expensive time-of-flight (eg:PMD) cameras. It was actually something I was hoping would come out before the end of the MAGIC 2010 competition, but unfortunately the release date was scheduled for after the end of the competition.&lt;br /&gt;&lt;br /&gt;The device was "hacked" almost immediately after its release and it has already been widely adopted, I think this will do wonders for the robotics/computer vision/stereo-vision community. So far all we have seen are relatively simple applications, but I'm sure people will start pushing the interpretation of the data to its limits soon, especially given that game-developers are now going to be playing with this kind of data. The Wii has already done fantastic things to push the knowledge of filtering and dealing with noisy sensor data to a wider audience, and I expect the Kinect will have a similar effect.&lt;br /&gt;&lt;br /&gt;It all started with &lt;a href="http://www.adafruit.com/blog/2010/11/04/the-open-kinect-project-the-ok-prize-get-1000-bounty-for-kinect-for-xbox-360-open-source-drivers/"&gt;Adafruit offering $2000 bounty for the Kinect hack&lt;/a&gt;, &lt;a href="http://www.adafruit.com/blog/2010/11/10/we-have-a-winner-open-kinect-drivers-released-winner-will-use-3k-for-more-hacking-plus-an-additional-2k-goes-to-the-eff/"&gt; which was promptly won by Hector Martin on the 10th of November&lt;/a&gt;.&lt;br /&gt;One of the first videos (now viral!) to do the rounds was from Oliver Kreylos showing the 3d data fused with image data and rendered in OpenGL.&lt;br /&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/7QrnwoO1-8A?fs=1&amp;amp;hl=en_US"&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/7QrnwoO1-8A?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Of course, it didn't stop there, other people are trying to hack the &lt;a href="http://ladyada.net/learn/diykinect/"&gt;rest of the USB Kinect protocol for the inclinometer and motor controls&lt;/a&gt;, and trying to &lt;a href="http://blog.makezine.com/archive/2010/11/how-to_modded_camera_looks_at_kinec.html"&gt;figure out how the Kinect IR works&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Willow Garage has already begun work on &lt;a href="http://www.willowgarage.com/blog/2010/11/22/kinect-ros-moving-forward-quickly"&gt;integrating the Kinect to ROS&lt;/a&gt; including calibration functions, and &lt;a href="http://singularityhub.com/2010/11/17/hacked-irobot-uses-xbox-kinect-to-see-the-world-obey-your-commands-video/"&gt;Philip Robbel managed to integrate the Kinect with a Hokuyo to do visual SLAM (using MRPT)&lt;/a&gt; only 7 days after the hack was released.&lt;br /&gt;&lt;object width="640" height="390"&gt;&lt;param name="movie" value="http://www.youtube.com/v/dRPEns8MS2o&amp;rel=0&amp;hl=en_US&amp;feature=player_embedded&amp;version=3"&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/dRPEns8MS2o&amp;rel=0&amp;hl=en_US&amp;feature=player_embedded&amp;version=3" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="390"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Hopefully we will see more &lt;a href="http://vimeo.com/17095170"&gt;practical uses for the Kinect&lt;/a&gt; soon! Wired published a nice &lt;a href="http://www.wired.co.uk/magazine/archive/2010/11/features/the-game-changer"&gt;story on the development path at Microsoft of the Kinect&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The best thing about this "hack" is that it has inspired others to do the same, most notably the &lt;a href="http://robotbox.net/blog/gallamine/open-lidar-project-hack-neato-xv-11-lidar-200-bounty"&gt;$800 reward for hacking the Neato Robotics XV-11 vacuum cleaner LIDAR&lt;/a&gt;. (&lt;a href="http://www.binary-apotheosis.com/had/RevoLDS_Whitepaper.pdf"&gt;Whitepaper here!&lt;/a&gt;). At only $300 (or even $30!) for a 360 degree, 6m range, 10Hz scanning LIDAR this would do great things for the robotics community as well. Sparkfun have already made some &lt;a href="http://www.sparkfun.com/news/490"&gt;interesting progress with their LIDAR tear-down&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Exciting times!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-6648895799026322581?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/6648895799026322581/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=6648895799026322581' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6648895799026322581'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6648895799026322581'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/11/microsoft-kinect-and-other-devices.html' title='Microsoft Kinect and other devices'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-7570612164330459135</id><published>2010-11-22T15:30:00.000+08:00</published><updated>2010-11-22T15:30:01.607+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><title type='text'>Batch import OBJ with Blender</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TOobc1GfZGI/AAAAAAAAAU8/an72vc0js3Q/s1600/Screen+shot+2010-11-22+at+3.27.09+PM.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TOobc1GfZGI/AAAAAAAAAU8/an72vc0js3Q/s1600/Screen+shot+2010-11-22+at+3.27.09+PM.png" /&gt;&lt;/a&gt;&lt;/div&gt;The OBJ importer in blender actually supports batch-import, to enable this you need to hold SHIFT when you select the importer from the File-&amp;gt;Import-&amp;gt;Wavefront (obj) menu. You will then be prompted to select a directory. Unfortunately, the importer will import each OBJ file into a separate (and incorrectly constructed) scene. To alter this you will need to edit the "import_obj.py" script and comment lines 1164 and 1165:&lt;br /&gt;&lt;pre&gt;for f in files:&lt;br /&gt;   #scn= bpy.data.scenes.new( stripExt(f) )&lt;br /&gt;   #scn.makeCurrent()&lt;br /&gt;&lt;/pre&gt;Saves you from having to write a batch import script yourself! A great utility to convert to OBJ files from various formats (with a batch-convert mode!) is &lt;a href="http://www.okino.com/"&gt;polytrans&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-7570612164330459135?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/7570612164330459135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=7570612164330459135' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7570612164330459135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7570612164330459135'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/11/batch-import-obj-with-blender.html' title='Batch import OBJ with Blender'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nHcDA3NyAms/TOobc1GfZGI/AAAAAAAAAU8/an72vc0js3Q/s72-c/Screen+shot+2010-11-22+at+3.27.09+PM.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-2926638203121499345</id><published>2010-11-18T20:10:00.001+08:00</published><updated>2010-11-18T20:10:40.594+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='magic2010'/><title type='text'>Team MAGICian/WAMbot takes 4th place!</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TOUW1Yg9baI/AAAAAAAAAUk/oteXJJZJZ4c/s1600/53926_171694029524829_132548153439417_481714_6163602_o%25282%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="262" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TOUW1Yg9baI/AAAAAAAAAUk/oteXJJZJZ4c/s400/53926_171694029524829_132548153439417_481714_6163602_o%25282%2529.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;All of our teams hard work has paid off as we claimed 4th place in the MAGIC 2010 competition! Our system was actually very close to what the top two teams had implemented, and with a bit of luck we might have been able to snatch a prize. Maybe next time! &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/_nHcDA3NyAms/TOUW53wxjCI/AAAAAAAAAUo/BZIwW4w_UpM/s1600/MAGIC_FINALISTS_DSTOS.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="166" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TOUW53wxjCI/AAAAAAAAAUo/BZIwW4w_UpM/s400/MAGIC_FINALISTS_DSTOS.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Above is a photo composition by Rob Reid of all the robots at the challenge stand, ordered from 1st to last (Left to Right). Team Michigan came in 1st, followed by University of Pennsylvania, and RASR took 3rd place. It's been a great opportunity to talk to all the other teams and see how they solved their problems and to see how many of the same headaches we all had. The LWC was a great place to meet and greet a number of industry people and also a nice crowd from DSTO who showed a lot of interest in what we have done. It was great to get so much positive feedback from everyone on our system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-2926638203121499345?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/2926638203121499345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=2926638203121499345' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/2926638203121499345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/2926638203121499345'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/11/team-magicianwambot-takes-4th-place.html' title='Team MAGICian/WAMbot takes 4th place!'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nHcDA3NyAms/TOUW1Yg9baI/AAAAAAAAAUk/oteXJJZJZ4c/s72-c/53926_171694029524829_132548153439417_481714_6163602_o%25282%2529.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-8382231981657598449</id><published>2010-11-12T20:11:00.025+08:00</published><updated>2010-11-18T20:33:43.338+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='magic2010'/><title type='text'>Ram Shed Challenge</title><content type='html'>The Ram Shed challenge was a media-event for the MAGIC 2010 competition. It was our first chance to see all the other teams robots and a chance to see them all at work. Our robots performed very well one the day and navigated the maze better than any other team, the entire open section of the maze was explored fully autonomously requiring no human interaction at any point. All of this despite the fact our wifi gear was mounted outside and failed during the rain, after a few minutes we were able to replace it and continue our mapping operations!&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/TOUb0VbqiKI/AAAAAAAAAUs/aFpyq9al1hA/s1600/ramshed-startup.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TOUb0VbqiKI/AAAAAAAAAUs/aFpyq9al1hA/s200/ramshed-startup.jpg" width="131" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TOUb7cl3BGI/AAAAAAAAAUw/lfEoqLn3IXw/s1600/ramshed.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="131" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TOUb7cl3BGI/AAAAAAAAAUw/lfEoqLn3IXw/s200/ramshed.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;The photos show our robots at the starting line, followed by them moving off in the starting arena, then navigating the maze, and finally the prize.  &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TOUcF8yicOI/AAAAAAAAAU0/Z8nl5VaB1n0/s1600/ramshed-maze.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="133" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TOUcF8yicOI/AAAAAAAAAU0/Z8nl5VaB1n0/s200/ramshed-maze.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TOUcapOt8gI/AAAAAAAAAU4/2zMmqwaOMX0/s1600/ramshed-prize.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="132" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TOUcapOt8gI/AAAAAAAAAU4/2zMmqwaOMX0/s200/ramshed-prize.JPG" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;A fabulous effort by our team, and I'm extremely proud of our achievements on this day!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-8382231981657598449?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/8382231981657598449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=8382231981657598449' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8382231981657598449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8382231981657598449'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/11/ram-shed-challenge.html' title='Ram Shed Challenge'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/TOUb0VbqiKI/AAAAAAAAAUs/aFpyq9al1hA/s72-c/ramshed-startup.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-4978845611146859543</id><published>2010-11-07T21:00:00.000+08:00</published><updated>2010-11-07T21:00:36.877+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='magic2010'/><title type='text'>Team MAGICian</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TMySsF4EghI/AAAAAAAAAUg/fmT5jnPDWg4/s1600/MAGIC-logo-_82.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="221" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TMySsF4EghI/AAAAAAAAAUg/fmT5jnPDWg4/s320/MAGIC-logo-_82.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Our MAGIC 2010 test day is over, so it's time to catch up on some sleep!&lt;br /&gt;Looking forward to seeing how the other teams will perform.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-4978845611146859543?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/4978845611146859543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=4978845611146859543' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/4978845611146859543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/4978845611146859543'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/11/team-magician.html' title='Team MAGICian'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_nHcDA3NyAms/TMySsF4EghI/AAAAAAAAAUg/fmT5jnPDWg4/s72-c/MAGIC-logo-_82.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-8626588364158612657</id><published>2010-10-31T05:48:00.000+08:00</published><updated>2010-10-31T05:48:53.141+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='magic2010'/><title type='text'>MAGIC 2010 - Adelaide</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TMySsF4EghI/AAAAAAAAAUg/fmT5jnPDWg4/s1600/MAGIC-logo-_82.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="221" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TMySsF4EghI/AAAAAAAAAUg/fmT5jnPDWg4/s320/MAGIC-logo-_82.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;We are off to Adelaide for the MAGIC 2010 finals.&lt;br /&gt;Looking forward to meeting the other teams, and hope it doesn't rain!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-8626588364158612657?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/8626588364158612657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=8626588364158612657' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8626588364158612657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8626588364158612657'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/10/magic-2010-adelaide.html' title='MAGIC 2010 - Adelaide'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_nHcDA3NyAms/TMySsF4EghI/AAAAAAAAAUg/fmT5jnPDWg4/s72-c/MAGIC-logo-_82.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-1083568948058696374</id><published>2010-10-27T10:43:00.000+08:00</published><updated>2010-10-27T10:43:51.148+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='COLLADA'/><category scheme='http://www.blogger.com/atom/ns#' term='raytracing'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><category scheme='http://www.blogger.com/atom/ns#' term='PAL'/><title type='text'>Convex Hull Generation in Blender</title><content type='html'>Convex hulls are very useful for a number of optimized calculations such as fast &lt;a href="http://adrianboeing.blogspot.com/2010/02/intersection-of-convex-hull-with-line.html"&gt;intersection tests&lt;/a&gt;, fast spatial subdivision, and other early-out's used in computer graphics, computational physics and robotics.&lt;br /&gt;&lt;br /&gt;When I implemented convex hull generation and convex decomposition in &lt;a href="http://pal.sf.net/"&gt;PAL&lt;/a&gt; I first used &lt;a href="http://www.qhull.org/"&gt;qhull&lt;/a&gt; and leveraged code from &lt;a href="http://www.tokamakphysics.com/"&gt;tokamak physics&lt;/a&gt;, but then used code by &lt;a href="http://www.melax.com/"&gt;Stan Melax&lt;/a&gt; and &lt;a href="http://www.codesuppository.blogspot.com/"&gt;John Ratcliff&lt;/a&gt; for &lt;a href="http://pal.sf.net/"&gt;PAL&lt;/a&gt;. Recently my work at &lt;a href="http://www.transmin.com.au/"&gt;Transmin&lt;/a&gt; has required generation of a number of Convex hulls, and so I combined these snippets of old code to create a plug-in for &lt;a href="http://www.blogger.com/www.blender.org/"&gt;Blender&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The Blender plugin creates a bounding convex hull of the selected object.&lt;br /&gt;It calls an external executable 'convex' which creates a convex hull based on an intermediate OBJ file.&lt;br /&gt;&lt;br /&gt;Installing the plugin requires you to compile the code to generate the 'convex' executable, and copying the python code into Blender's scripts directory.&lt;br /&gt;&lt;br /&gt;To compile the C code on linux/osx:&lt;br /&gt;&lt;pre&gt;g++ createhull.cpp hull.cpp -o convex&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Place the object_boundinghull.py script in your ".blender/scripts" directory.&lt;br /&gt;&lt;br /&gt;On OSX Blender default installs to:&lt;br /&gt;&lt;pre&gt;/Applications/blender-2.49b-OSX-10.5-py2.5-intel/blender.app/Contents/MacOS&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TMeOm6eSV4I/AAAAAAAAAUc/B1QSMHm9GO0/s1600/split-bp.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="143" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TMeOm6eSV4I/AAAAAAAAAUc/B1QSMHm9GO0/s200/split-bp.png" width="200" /&gt;&lt;/a&gt;Once the plugin is installed you can start creating convex hulls. You can select an object in blender and cut it into smaller objects to manually decompose the hulls. To do this, you can use the Knife tool (K) or split objects in edit-mode with 'P'. (Selection tools like 'B' and manual alignment of cameras ('N', Numpad 5) will help a lot).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TMeOlkyjmnI/AAAAAAAAAUU/xUg2SabK0oo/s1600/convexscript.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="120" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TMeOlkyjmnI/AAAAAAAAAUU/xUg2SabK0oo/s320/convexscript.png" width="320" /&gt;&lt;/a&gt;Once you have the objects you would like to generate hulls for select one, and run the "Bounding Convex Hull" script. It will ask you to confirm the creation of the hull. The new hull will have the same name as the original object and have ".hull" appended to its name.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/TMeOmfFXbUI/AAAAAAAAAUY/fMSl31xr-0E/s1600/convexhull.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TMeOmfFXbUI/AAAAAAAAAUY/fMSl31xr-0E/s200/convexhull.png" width="158" /&gt;&lt;/a&gt; &lt;br /&gt;The plugin will generate a new object that represents the convex hull of  the selected object, with the same transforms as the original object.  (Ctrl-A to apply all down to the mesh, note: Blender 2.49 does not let  you apply translation transforms, but Blender 2.5+ does). You can then decimate the hull to reduced the number of tri's used to represent your object. (Editing F9, under modifiers, select 'Add Modifier', decimate, and reduce the ratio).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;Now your ready to export your scene for all your raytracing and collision detection needs!&lt;br /&gt;&lt;br /&gt;Thanks to &lt;a href="http://www.transmin.com.au/"&gt;Transmin Pty Ltd&lt;/a&gt; for allowing me to release this plugin back to the Blender community under the GPL.&lt;br /&gt;&lt;br /&gt;Follow the link to &lt;a href="http://www.adrianboeing.com/files/boundinghull.zip"&gt;download the Blender Bounding Convex Hull plugin&lt;/a&gt; to generate editable bounding volumes directly in Blender.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-1083568948058696374?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/1083568948058696374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=1083568948058696374' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/1083568948058696374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/1083568948058696374'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/10/convex-hull-generation-in-blender.html' title='Convex Hull Generation in Blender'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nHcDA3NyAms/TMeOm6eSV4I/AAAAAAAAAUc/B1QSMHm9GO0/s72-c/split-bp.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-5225387750566012092</id><published>2010-10-10T18:18:00.002+08:00</published><updated>2010-10-16T19:01:45.134+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Using BZR</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TLGS2ZZmlKI/AAAAAAAAAUQ/YTKF5PrajFs/s1600/workflows_centralized.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="226" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TLGS2ZZmlKI/AAAAAAAAAUQ/YTKF5PrajFs/s320/workflows_centralized.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;BZR supports a number of different &lt;a href="http://wiki.bazaar.canonical.com/Workflows"&gt;workflows&lt;/a&gt;. The most common one is "Centralized", which allows you to use BZR just like CVS or SVN. You just type "bzr commit" (save changes) and "bzr update" (get changes).&lt;br /&gt;&lt;br /&gt;However, BZR has the advantage of being a distributed system and thus gives you the option of branching, working remotely (and still having version control), and then merging your changes back to the main trunk.&lt;br /&gt;&lt;br /&gt;You can do this in a few easy steps:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Make a copy of your code, by making a new "branch" of the code. Example:&lt;br /&gt;&lt;pre&gt;(On LOCAL)&lt;br /&gt;bzr branch WAMbot WAMbotAdriansBranch&lt;br /&gt;&lt;/pre&gt;In future, you can keep this branch up to date by using "bzr pull" from the branch.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Copy the branch to your target (eg: a robot / embedded PC or usb-stick). If you copy from the USB stick to the target you will need an extra step to go back.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Work with the source code on the target. After you have made changes just type "bzr commit" (on the target). This will commit to your local branch. &lt;br /&gt;&lt;br /&gt;Now you have the advantage of being able to revert any changes that you make while working away, without needing a connection to the main server.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;If you copied from the USB stick, and you want to save the changes back to it, type (at the target): "bzr push LOCATION" (Where LOCATION is the USB disk drive). Example:&lt;br /&gt;&lt;pre&gt;(On TARGET)&lt;br /&gt;bzr push "e:/WAMbotAdriansBranch"&lt;br /&gt;&lt;/pre&gt;from the bzr directory on the robot.&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Now merge with your local repository, from your own bzr directory type:&lt;br /&gt;bzr merge LOCATION (Where LOCATION is the USB disk drive, or shared folder) Example: &lt;pre&gt;(On LOCAL)&lt;br /&gt;bzr merge X:\WAMbotBranch&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Now you can commit them to the central server! (Just use bzr commit like always)&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;This saves you from having to keep track of your source code and merge things manually.  Some more helpful BZR tips: &lt;br /&gt;&lt;ul&gt;&lt;li&gt; bzr update (get the latest code from the server)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; bzr commit (save your code to the server)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; bzr add (add some files to repo)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; bzr whoami (get/set who you are)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; bzr revno (get current revision number)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; bzr diff -r REVISION (eg: 1000) filename (tells you the differences in a file since a specified revision) &lt;br /&gt;&lt;br /&gt;There are a number of revision flags:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; bzr diff -r last:5 (compare with 5 revision ago)&lt;br /&gt;&lt;li&gt;bzr diff -r date:yesterday (compare with yesterdays revision)&lt;br /&gt;&lt;li&gt;bzr diff -r date:YYYY-MM-DD (compare with a dated revision)&lt;br /&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt; bzr commit --local (commit to your own local repository, so you can easily undo changes. Note: you may need to bind/unbind, so branching as described above is probably better)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; bzr revert (undo your changes)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; bzr log (show commit comments)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; bzr log -r REVISION.. (show all comments since given revision. Example: "bzr log -r1000..")&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;BZR also has a number of plugins, including one to &lt;a href="http://doc.bazaar.canonical.com/plugins/en/testrunner-plugin.html"&gt;run a command before a commit&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-5225387750566012092?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/5225387750566012092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=5225387750566012092' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5225387750566012092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5225387750566012092'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/10/using-bzr.html' title='Using BZR'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nHcDA3NyAms/TLGS2ZZmlKI/AAAAAAAAAUQ/YTKF5PrajFs/s72-c/workflows_centralized.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-7510283424886317381</id><published>2010-09-24T14:51:00.000+08:00</published><updated>2010-09-24T14:51:08.636+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><title type='text'>Circular Motion in 2D for graphics and robotics</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;For a number of applications circular motion in 2D is useful, in particular simplified kinematic representations for mobile robot simulation and control. There are a number of different ways of representing this motion.&lt;br /&gt;&lt;br /&gt;First it is helpful to remember a position on a circle can be described parametrically by:&lt;br /&gt;[x,y] = [r*cos(theta), r*sin(theta)]&lt;br /&gt;or alternatively, r =sqrt( x^2 + y^2).&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt; As a circular variation of the standard 2D particle, we just add an angular velocity (omega) and angular orientation (theta). For a standard 2D particle we can describe its velocity (v) in terms of acceleration (a) and a delta in time (dt) (v += a*dt; x+= v*dt). We can modify this to include the parametric circle representation:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;theta += omega * dt;&lt;br /&gt;x+=v*dt*cos(theta);&lt;br /&gt;y+=v*dt*sin(theta);&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;The problem with the above method is that it is in-exact and relies on an integrator. The 2D velocity/angular velocity representation can easily be fully solved analytically. The radius of a circle produced by a given velocity (v) and angular velocity (omega, or w) is:&lt;br /&gt;r = | v / w |&lt;br /&gt;We can modify the parametric representation to include an offset for the centre of motion: &lt;br /&gt;[x,y] = [r*cos(theta) + xc, r*sin(theta) + yc]&lt;br /&gt;Thus, given an initial x,y,theta we can find the centre of the circle of motion as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;xc = x - (v/w)*sin(theta)&lt;br /&gt;yc = y + (v/w)*cos(theta)&lt;br /&gt;&lt;/pre&gt;Now we can update the position of the robot:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;theta += w * dt;&lt;br /&gt;x = xc + (v/w) sin(theta)&lt;br /&gt;y = yc - (v/w) cos(theta)&lt;br /&gt;&lt;/pre&gt;We can expand this into a single line as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;x+= -(v/w)*sin(theta) + (v/w)*sin(theta+w*dt)&lt;br /&gt;y+= -(v/w)*cos(theta) - (v/w)*cos(theta+w*dt)&lt;br /&gt;theta += omega * dt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TJxKHq_UCBI/AAAAAAAAAUM/M8q5eCoxJ6A/s1600/motionmodel.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="225" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TJxKHq_UCBI/AAAAAAAAAUM/M8q5eCoxJ6A/s320/motionmodel.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Which is the form many robotics papers use.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Finally, we may wish to represent the motion in terms of two given x,y coordinates and solve for the translation and rotation required to reach them (as is the case for odometry calculations). In this case, we can represent any movement from an original set of coordinates [x,y,theta] to a new set [x',y',theta'] as first a rotation and translation to bring you to any new x' and y', followed by another rotation to bring you to the final theta'. Using triangle trigonometry this is:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;deltaRot1 = atan2(y'-y,x'-x) - theta&lt;br /&gt;deltaTrans = sqrt( (x-x')^2 + (y-y')^2 )&lt;br /&gt;deltaRot2 = theta' - theta - deltaRot1 &lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;There are of course many more ways of representing circular motion, but the above are the most common in computer graphics and robotics.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-7510283424886317381?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/7510283424886317381/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=7510283424886317381' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7510283424886317381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7510283424886317381'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/09/circular-motion-in-2d-for-graphics-and.html' title='Circular Motion in 2D for graphics and robotics'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_nHcDA3NyAms/TJxKHq_UCBI/AAAAAAAAAUM/M8q5eCoxJ6A/s72-c/motionmodel.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-5400001648095633623</id><published>2010-09-14T09:21:00.000+08:00</published><updated>2010-09-14T09:21:14.284+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='compilers'/><title type='text'>Intel Compiler on Linux</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/TI7N6HPj0II/AAAAAAAAAUE/DzckOpdmovs/s1600/icc.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TI7N6HPj0II/AAAAAAAAAUE/DzckOpdmovs/s320/icc.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt; Make sure you have access to root. (eg: sudo su root, passwd)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Make sure you have your build environment set up. eg:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;sudo apt-get install gcc&lt;br /&gt;sudo apt-get install build-essential&lt;br /&gt;sudo apt-get install g++&lt;br /&gt;sudo apt-get install rpm&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt; ICC requires older standard C libraries, libstdc++5, so you can get them for Ubuntu from:&lt;br /&gt;&lt;a href="http://packages.debian.org/stable/base/libstdc++5"&gt;Package: libstdc++5&lt;/a&gt;. You just need to download the i386 package. (eg from the &lt;a href="http://ftp.iinet.net.au/debian/debian/pool/main/g/gcc-3.3/libstdc++5_3.3.6-18_i386.deb"&gt;Australian mirror&lt;/a&gt;, by using wget [url]), and then install it, eg: "sudo dpkg -i libstdc++5_3.3.6-18_i386.deb".&lt;br /&gt;If you don't do this you may get the following error messages:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Missing critical pre-requisite&lt;br /&gt;-- missing system commands&lt;br /&gt;&lt;br /&gt;The following required for installation commands are missing:&lt;br /&gt;libstdc++.so.5 ( library)&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt; Download ICC&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Unzip (tar -xvf  filename)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; ./install.sh&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Choose to install for all (1)&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Read "welcome" message follow instructions for licence, etc.&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Activate your software (1) and provide the serial number that came in your email. You should see "Activation Completed Successfully"&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Install the software (requires 3.35 gigs). You should see a message "Checking the prerequisites. It can take several minutes. Please wait…".&lt;br /&gt;&lt;/li&gt;&lt;li&gt; You might see:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Missing optional pre-requisite&lt;br /&gt;-- No compatible Java* Runtime Environment (JRE) found&lt;br /&gt;-- operating system type is not supported.&lt;br /&gt;-- system glibc or kernel version not supported or not detectable&lt;br /&gt;-- binutils version not supported or not detectable&lt;br /&gt;&lt;/pre&gt;The JRE you need for the visual debugger, otherwise you can safely continue.&lt;br /&gt;&lt;/li&gt;&lt;li&gt; The installer then asks which components to install, eg "Intel(R) C++ Compiler Professional Edition for Linux*", just press "1. Install" to continue. It should state "component installed successfully."&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Setup the paths, you can use the iccvars.sh in /opt/intel/Compiler/11.1/073/bin to setup everything for you. (eg: source /opt/intel/Compiler/11.1/073/bin/iccvars.sh ia32). You may wish to put it into your .bashrc file.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;That's it! Type "icc" to invoke for C files or "icpc" for C++ files. For standard makefiles use "make CXX=icpc"&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;On a 1GHz VIA Esther processor, GCC 4.4.1, with -O2 -march=c3-2: &lt;br /&gt;&lt;pre&gt;real 0m16.855s&lt;br /&gt;user 0m16.849s&lt;br /&gt;sys 0m0.004s&lt;br /&gt;&lt;/pre&gt;And, with ICC 11.1, with -O2: &lt;br /&gt;&lt;pre&gt;real 0m11.369s&lt;br /&gt;user 0m11.361s&lt;br /&gt;sys 0m0.008s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;An instant 45% speedup! Unfortunately not all code makes such a big change, some other compute-intensive code I tested only got a 4% speedup. In any case I'd say its worth it!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-5400001648095633623?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/5400001648095633623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=5400001648095633623' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5400001648095633623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5400001648095633623'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/09/intel-compiler-on-linux.html' title='Intel Compiler on Linux'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/TI7N6HPj0II/AAAAAAAAAUE/DzckOpdmovs/s72-c/icc.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-5317341724190300663</id><published>2010-09-12T19:58:00.000+08:00</published><updated>2010-09-12T19:58:03.199+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='GPGPU'/><category scheme='http://www.blogger.com/atom/ns#' term='fluid'/><title type='text'>SIGGRAPH 2010 Course Papers Overview</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TIy_w47MnHI/AAAAAAAAAT0/loNF5NLJ_KQ/s1600/toystory3-ssao.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TIy_w47MnHI/AAAAAAAAAT0/loNF5NLJ_KQ/s320/toystory3-ssao.png" /&gt;&lt;/a&gt;&lt;/div&gt;I've managed to work through the SIGGRAPH 2010 course content that relates to realtime rendering. I quite liked the Toy Story 3 rendering techniques and realtime rendering survey by nVidia- just because they give a nice overview. As always, there are a number of great presentations, and I've listed the ones that I found interesting below.&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Toy Story 3 : The Video Game Rendering Techniques from &lt;a href="http://avalanchesoftware.blogspot.com/"&gt;Avalanche Software&lt;/a&gt; gives a great (211 page!) overview of a number of lighting issues for the game including SSAO (various optimizations/approximations for how/where to sample, faking more samples and dealing with large differences in depth), ambient lighting (without needing to bake it or do GI) and various aspects on shadows. A great read!&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Surveying Real-Time Rendering Algorithms by David Luebke from nVidia gives an excellent short overview of a number of recent developments in realtime rendering algorithms including stochastic transparency (ie : transparency via random sampling), sample distribution for shadow maps (partitioning the scene in light-space), alias-free shadow maps, append-consume order-independent-transparency (sorting per-pixel &amp;amp; linked-lists), progressive photon mapping, image-space photon mapping, ambient occlusion volumes (how to speed it up with bitwise occlusion mask for each triangle - one per edge, and one for the triangle plane), stochastic rasterization (of 4d triangles) &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Keeping Many Cores Busy: Scheduling the Graphics Pipeline by Jonathan Ragan-Kelly from MIT gives a great overview of the graphics pipeline stages (from Input Assembler, Vertex Shader, Primitive Assembler, Tesselation, Geometry Shader, Rasterizer, Pixel Shader, and finally Output Blending) and load balancing.&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Uncharted 2 - Character Lighting and Shading by John Hable from Naughty Dog gives a fabulous overview of rendering issues with skin (in a lot of detail!), hair and clothes.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Bending the Graphics Pipeline by Johan Andersson from DICE describes tile-based deferred shading (for GPU and SPU), morphological antialiasing and analytical ambient occlusion.&lt;br /&gt;&lt;/li&gt;&lt;li&gt; A real-time Radiosity Architecture for Video Games by Sam Martin and Per Einarsson from DICE/Geomerics introduce the 'Enlighten' system for realtime GI - it gives a nice overview.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Evolving the Direct3D Pipeline for Real-­time Micropolygon Rendering by Kayvon Fatahalian from Stanford University gives an interesting insight on Micropolygon rendering on current GPU pipelines.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Water Flow in Portal 2 by Alex Vlachos - I've already written about this previously, just another realtime technique for faking the simulation and rendering of water flow.&lt;br /&gt;&lt;/li&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/TIy_-qMbn9I/AAAAAAAAAT8/jDXUnV6LQuI/s1600/borderlands-sobel.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TIy_-qMbn9I/AAAAAAAAAT8/jDXUnV6LQuI/s320/borderlands-sobel.png" /&gt;&lt;/a&gt;&lt;li&gt; Making Concept Real For Borderlands by Gearbox Software contains some nice examples of their concept art, the development change from photorealistic to stylistic rendering and art (and the code/artist balance), and the sobel edge filter they used.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The notes from the volumetric course was broken into parts:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt; "Resolution Independent Volumes" - which describes the "Field Expression Language Toolkit", cloud modelling (via density displacement), morphing objects (by using the Nacelle Algorithm to generate warp fields), cutting models, fluid dynamics, gridless advection, and semi-lagrangian mapping (balancing between grids and non-grids). &lt;br /&gt;&lt;/li&gt;&lt;li&gt; "Mantra Volume Rendering" - this describes the volume rendering engine for Houdini. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;"Volumetric Modeling and Rendering"  describes the volumetrics library/API  developed at Dreamworks.   &lt;br /&gt;&lt;/li&gt;&lt;li&gt; "Double Negative Renderer B" (used in Batman Begins, Harry Potter, etc.) describes the workflow and various shaders (Fluid, Particle, Voxel, Fire, Smoke) in DNB&lt;br /&gt;&lt;/li&gt;&lt;li&gt; "Volume Rendering at Sony Pictures Imageworks". The section from Sony Imageworks included an overview of their pipeline and content on their open source field/fluid tools. &lt;br /&gt;&lt;/li&gt;&lt;/ol&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/17188375-5317341724190300663?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/5317341724190300663/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=5317341724190300663' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5317341724190300663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5317341724190300663'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/09/siggraph-2010-course-papers-overview.html' title='SIGGRAPH 2010 Course Papers Overview'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nHcDA3NyAms/TIy_w47MnHI/AAAAAAAAAT0/loNF5NLJ_KQ/s72-c/toystory3-ssao.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-6365792080990210805</id><published>2010-09-08T22:36:00.000+08:00</published><updated>2010-09-08T22:36:02.310+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='GPGPU'/><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><title type='text'>Catchup Post: Graphics &amp; GPU's &amp; Physics</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TIee3StDf9I/AAAAAAAAATs/ruoRlQ_w35o/s1600/siggraph2010" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TIee3StDf9I/AAAAAAAAATs/ruoRlQ_w35o/s320/siggraph2010" /&gt;&lt;/a&gt;&lt;/div&gt;A long overdue catchup post for various interesting things I've spotted over the last two or three months. &lt;a href="http://www.blogger.com/www.siggraph.org/"&gt;SIGGRAPH&lt;/a&gt; recently finished, so it really deserves a round-up, although I haven't had time to review all the interesting things.&lt;br /&gt;The annual tutorial on &lt;br /&gt;&lt;a href="http://sglab.kaist.ac.kr/%7Esungeui/Collision_tutorial/"&gt;realtime collision&lt;/a&gt; had some interesting presentations, I quite liked the one from &lt;a href="http://bulletphysics.org/"&gt;Erwin Coumans (Bullet)&lt;/a&gt; this year - it gives a good overview of the recent advances in the Bullet engine including the GPU optimizations. Simon Green also has a presentation on &lt;a href="http://developer.download.nvidia.com/presentations/2010/gdc/Direct3D_Effects.pdf"&gt; CUDA SPH rendering&lt;/a&gt; (also see &lt;a href="http://cs.nyu.edu/%7Ejihun/pmwiki/?n=Main.Publications"&gt;Jihun Yu's particle fluid surface reconstruction&lt;/a&gt;) and another open source &lt;a href="http://code.google.com/p/gpusphsim/"&gt;GPU SPH simulation from HPC lab&lt;/a&gt;.&lt;br /&gt;The &lt;a href="http://advances.realtimerendering.com/s2010/index.html"&gt;realtime graphics tutorial&lt;/a&gt;, &lt;a href="http://graphics.cs.williams.edu/courses/SRG10/"&gt;stylized rendering&lt;/a&gt;, &lt;a href="http://magnuswrenninge.com/volumetricmethods"&gt;volumetrics&lt;/a&gt;, and  &lt;a href="http://bps10.idav.ucdavis.edu/"&gt;programmable shaders&lt;/a&gt;  has some great stuff that I'll look into in more detail in a future post. Ofcourse there is also always &lt;a href="http://kesen.realtimerendering.com/sig2010.html"&gt;the SIGGRAPH 2010 papers list&lt;/a&gt;, and &lt;a href="http://kesen.realtimerendering.com/siga2010Papers.htm"&gt;SIGGRAPH asia papers&lt;/a&gt; (again more on this later..).&lt;br /&gt;&lt;br /&gt;Some GPGPU software/links:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://developer.amd.com/stream"&gt;AMD's Stream SDK&lt;/a&gt; - the new version allows printf in OpenCL kernels - very handy for debugging and OpenCL1.1 support.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.amd.com/samples/opencl/Pages/default.aspx"&gt;AMD's OpenCL sample page&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.brightsideofnews.com/news/2010/5/27/why-intel-larrabee-really-stumbled-developer-analysis.aspx?pageid=1"&gt; an interesting article on larrabee's demise&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.cuvilib.com/downloads/"&gt;CUDA Vision Library&lt;/a&gt; - another library, but this one has quite a few functions including optical flow and hough transforms plus some color space conversions.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.amd.com/gpu/ATIStreamSDK/pages/TutorialOpenCL.aspx"&gt;AMD OpenCL tutorial&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://alice.loria.fr/index.php/software/4-library/23-opennl.html"&gt;OpenNL&lt;/a&gt; has some GPU based sparse matrix structures and iterative linear systems &amp;amp; least-squares solvers, etc.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/back40computing/"&gt;Back40&lt;/a&gt; has a fast radix sort.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://enja.org/2010/08/27/adventures-in-opencl-part-2-particles-with-opengl/"&gt;OpenCL and OpenGL interoperability&lt;/a&gt; particle system example.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;and a now-old-hat story on the&lt;a href="http://gpgpu.org/2010/05/31/gpu-supercomputer-2-in-top500"&gt;GPU supercomputer in the top 500 list&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;and &lt;a href="http://spc.unige.ch/mptl"&gt;MPTL&lt;/a&gt; is a parallel version of the STL algorithms.  &lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Some physics links: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;A new version of the &lt;a href="http://devsupport.ageia.com/ics/support/default.asp?deptID=1949"&gt;PhysX SDK&lt;/a&gt; is available with some SSE optimizations and the source code to the tetgen program. A new version of the PhysX visual debugger is also available. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://physbam.stanford.edu/%7Emlentine/research.html"&gt;Creature Control in a Fluid Environment&lt;/a&gt; - an interesting paper, reminds me that I should really publish my PhD at some point...&lt;br /&gt;&lt;/li&gt;&lt;li&gt;While we are on the topic of underwater physics, &lt;a href="http://graphics.ucmerced.edu/%7Eoozgen/paper-tog-10/"&gt;Underwater Cloth Simulation with Fractional Derivatives&lt;/a&gt; is worth a look.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://graphics.eecs.berkeley.edu/site_root/papers/Wang-EBW-2010-07/"&gt;Example based wrinkles for cloth simualtion&lt;/a&gt; an interesting take on one of the more difficult aspects of good cloth simulation.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://sglab.kaist.ac.kr/FASTCD/"&gt;FASTCD - fracture aware collision detection&lt;/a&gt; - a lot of good things coming out of KAIST recently in this field.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://graphics.eecs.berkeley.edu/site_root/papers/Wicke-DLR-2010-07/"&gt;Dynamic Local Remeshing for Elastoplastic Simulation&lt;/a&gt;, is a Finite Elements method for achieving a range of physical material behaviors. Neat.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Some graphics links: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Alex describes the &lt;a href="http://code4k.blogspot.com/2010/08/making-of-ergon-4k-pc-intro.html"&gt;making of the Ergon 4k intro&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;ryg has a great post on &lt;a href="http://fgiesen.wordpress.com/2010/08/23/carry-save-adders-and-averaging-bit-packed-values/"&gt;optimzing packed pixel blend operations&lt;/a&gt; for non-SIMD systems.. nifty! I wish I knew this previously! (ryg also has an interesting post on &lt;a href="http://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/#more-29"&gt;morton-codes&lt;/a&gt;, which you can use for organizing your data for easy n-dimensional nearest neighbor retrieval. See &lt;a href="http://www.codexon.com/posts/morton-codes"&gt;codexon's explanation&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I stumbled upon this interesting description of a &lt;a href="http://www.bencloward.com/shaders_globalIllum.shtml"&gt;global illumination shader&lt;/a&gt; including ambient occlusion, GI, bump maps, etc.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Kyle has a post on his implementation of  &lt;br /&gt;&lt;a href="http://graphicsrunner.blogspot.com/2010/08/water-using-flow-maps.html"&gt;animating water with flow-maps&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The excellent page on &lt;a href="http://meshula.net/wordpress/?p=145"&gt;screen space ambient occlusion at Meshula has been updated&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;NASA released a collection of &lt;a href="http://www.nasa.gov/multimedia/3d_resources/models.html"&gt;NASA 3d Models&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://sizecoding.blogspot.com/"&gt;Auld's blog&lt;/a&gt; has some interesting posts describing his 4k modeling tool, with some input from iq.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.ctrl-alt-test.fr/?page_id=7"&gt;GL minify&lt;/a&gt; to compress GLSL shaders.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Steve Hollasch has a nice &lt;br /&gt;&lt;a href="http://steve.hollasch.net/cgindex/index.html"&gt;collection of interesting graphics-related newsgroup posts&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;And finally a documentary on the history of the Future Crew demo group and Second Reality. Brings back the memories. &lt;object height="385" width="640"&gt;&lt;param name="movie" value="http://www.youtube.com/v/tdWs_ZJL2c8&amp;color1=0xb1b1b1&amp;color2=0xd0d0d0&amp;hl=en_US&amp;feature=player_embedded&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/tdWs_ZJL2c8&amp;color1=0xb1b1b1&amp;color2=0xd0d0d0&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-6365792080990210805?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/6365792080990210805/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=6365792080990210805' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6365792080990210805'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6365792080990210805'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/09/catchup-post-graphics-gpus-physics.html' title='Catchup Post: Graphics &amp; GPU&apos;s &amp; Physics'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nHcDA3NyAms/TIee3StDf9I/AAAAAAAAATs/ruoRlQ_w35o/s72-c/siggraph2010' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-3663710003101885918</id><published>2010-08-25T21:47:00.000+08:00</published><updated>2010-08-25T21:47:28.005+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Kalman filters - Part 2</title><content type='html'>In a &lt;a href="http://adrianboeing.blogspot.com/2010/05/kalman-filters.html"&gt;previous post I described kalman filters&lt;/a&gt; and gave a very simple example of a 1D filter implemented in C. In the real world, having a filter with three or more inputs is common. A standard 3rd order example would be a filter that considers the position, velocity and acceleration of a system.&lt;br /&gt;&lt;br /&gt;In this case you would have a 3x3 measurement matrix (H) (with the diagonal set to what you can measure), a 3x3 process noise matrix (Q), a 3x3 measurement noise matrix  (R), and a 3x3 state transition matrix. The standard transition matrix would simply contain v+=a*dt, x+=v*dt, but we can use a 2nd order leapfrog integrator to get better accuracy of our position from our acceleration data. So in total we have:&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/_nHcDA3NyAms/THUdr8X54QI/AAAAAAAAATE/_J7tC3pmA9A/s1600/eqn2375.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_nHcDA3NyAms/THUdr8X54QI/AAAAAAAAATE/_J7tC3pmA9A/s320/eqn2375.png" /&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/_nHcDA3NyAms/THUdyXHKWkI/AAAAAAAAATM/PQdLytpigkY/s1600/Qeqn2375.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="61" src="http://3.bp.blogspot.com/_nHcDA3NyAms/THUdyXHKWkI/AAAAAAAAATM/PQdLytpigkY/s200/Qeqn2375.png" width="200" /&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/_nHcDA3NyAms/THUd3QnW51I/AAAAAAAAATU/nPzEDdnnHCc/s1600/reqn2375.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="61" src="http://3.bp.blogspot.com/_nHcDA3NyAms/THUd3QnW51I/AAAAAAAAATU/nPzEDdnnHCc/s200/reqn2375.png" width="200" /&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/_nHcDA3NyAms/THUejIja2-I/AAAAAAAAATc/RENxSzue0cA/s1600/Feqn2375.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_nHcDA3NyAms/THUejIja2-I/AAAAAAAAATc/RENxSzue0cA/s320/Feqn2375.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;You can either solve this using the standard kalman matrix maths, but you will find that an &lt;a href="http://adrianboeing.blogspot.com/2010/05/inverting-matrix-svd-singular-value.html"&gt;SVD approach&lt;/a&gt; will give you more stable solutions. &lt;a href="http://opencv.willowgarage.com/"&gt;OpenCV&lt;/a&gt; is one library that already has the kalman matrix maths built in. To set up a kalman filter with OpenCV we just need to setup the matrices we need and call the appropriate cvKalman functions.&lt;br /&gt;&lt;br /&gt;(ugly) Code snippet follows:&lt;br /&gt;&lt;pre&gt;#ifndef KALMAN_H&lt;br /&gt;&lt;span style="color: blue;"&gt;#define&lt;/span&gt; KALMAN_H&lt;br /&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;/** OpenCV Kalman filter for 1st, 2nd and 3rd order position, velocity and acceleration data.&lt;br /&gt;    (c) Adrian Boeing&lt;br /&gt;    www.adrianboeing.com&lt;br /&gt; */&lt;/span&gt;&lt;br /&gt;#&lt;span style="color: blue;"&gt;include&lt;/span&gt; &amp;lt;cv.h&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;typedef&lt;/span&gt; &lt;span style="color: blue;"&gt;enum&lt;/span&gt; {&lt;br /&gt;    K_P = &lt;span style="color: maroon;"&gt;1&lt;/span&gt;, &lt;span style="color: green;"&gt;//position only&lt;/span&gt;&lt;br /&gt;    K_V = &lt;span style="color: maroon;"&gt;2&lt;/span&gt;, &lt;span style="color: green;"&gt;//velocity only&lt;/span&gt;&lt;br /&gt;    K_A = &lt;span style="color: maroon;"&gt;4&lt;/span&gt;, &lt;span style="color: green;"&gt;//acceleration only&lt;/span&gt;&lt;br /&gt;    K_PV = &lt;span style="color: maroon;"&gt;3&lt;/span&gt;, &lt;span style="color: green;"&gt;//position &amp;amp; velocity&lt;/span&gt;&lt;br /&gt;    K_PA = &lt;span style="color: maroon;"&gt;5&lt;/span&gt;, &lt;span style="color: green;"&gt;//position &amp;amp; acceleration&lt;/span&gt;&lt;br /&gt;    K_VA = &lt;span style="color: maroon;"&gt;6&lt;/span&gt;, &lt;span style="color: green;"&gt;//velocity &amp;amp; acceleration&lt;/span&gt;&lt;br /&gt;    K_PVA = &lt;span style="color: maroon;"&gt;7&lt;/span&gt; &lt;span style="color: green;"&gt;//position, velocity and acceleration&lt;/span&gt;&lt;br /&gt;} Kalman_e;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;class&lt;/span&gt; KalmanPVA {&lt;br /&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt;:&lt;br /&gt;    KalmanPVA(&lt;span style="color: blue;"&gt;int&lt;/span&gt; order, Kalman_e type, &lt;span style="color: blue;"&gt;float&lt;/span&gt; initial_pos, &lt;span style="color: blue;"&gt;float&lt;/span&gt; initial_vel, &lt;span style="color: blue;"&gt;float&lt;/span&gt; initial_accel, &lt;span style="color: blue;"&gt;float&lt;/span&gt; dt, &lt;span style="color: blue;"&gt;float&lt;/span&gt; process_noise[&lt;span style="color: maroon;"&gt;3&lt;/span&gt;], &lt;span style="color: blue;"&gt;float&lt;/span&gt; measurement_noise[&lt;span style="color: maroon;"&gt;3&lt;/span&gt;]) {&lt;br /&gt;        m_order = order;&lt;br /&gt;        &lt;span style="color: green;"&gt;//create the OpenCV kalman structures&lt;/span&gt;&lt;br /&gt;        kalman = cvCreateKalman(order, &lt;span style="color: maroon;"&gt;3&lt;/span&gt;, &lt;span style="color: maroon;"&gt;0&lt;/span&gt; );&lt;br /&gt;        z = cvCreateMat(&lt;span style="color: maroon;"&gt;3&lt;/span&gt;,&lt;span style="color: maroon;"&gt;1&lt;/span&gt;,CV_32FC1);&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: green;"&gt;//construct the transition matrix&lt;/span&gt;&lt;br /&gt;        SetDT(dt);&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: green;"&gt;//enable only the measurements we have!&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;int&lt;/span&gt; i=&lt;span style="color: maroon;"&gt;0&lt;/span&gt;;i&amp;lt;m_order;i++) {&lt;br /&gt;            cvmSet(kalman-&amp;gt;measurement_matrix,i,i,((type&amp;amp;&lt;span style="color: maroon;"&gt;7&lt;/span&gt;)&amp;gt;&amp;gt;i)&amp;amp;&lt;span style="color: maroon;"&gt;1&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: green;"&gt;//configure the process noise matrix&lt;/span&gt;&lt;br /&gt;        cvSetIdentity( kalman-&amp;gt;process_noise_cov,    cvRealScalar(&lt;span style="color: maroon;"&gt;1&lt;/span&gt;) ); &lt;span style="color: green;"&gt;//zero the matrix &lt;/span&gt;&lt;br /&gt;        &lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;int&lt;/span&gt; i=&lt;span style="color: maroon;"&gt;0&lt;/span&gt;;i&amp;lt;m_order;i++) {&lt;br /&gt;            cvmSet( kalman-&amp;gt;process_noise_cov,i,i, process_noise[i] ); &lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: green;"&gt;//configure the measurment noise matrix&lt;/span&gt;&lt;br /&gt;        cvSetIdentity( kalman-&amp;gt;measurement_noise_cov, cvRealScalar(&lt;span style="color: maroon;"&gt;1&lt;/span&gt;) ); &lt;span style="color: green;"&gt;//zero the matrix&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;int&lt;/span&gt; i=&lt;span style="color: maroon;"&gt;0&lt;/span&gt;;i&amp;lt;&lt;span style="color: maroon;"&gt;3&lt;/span&gt;;i++) {&lt;br /&gt;            cvmSet(kalman-&amp;gt;measurement_noise_cov,i,i,measurement_noise[i]);&lt;br /&gt;        }&lt;br /&gt;        cvSetIdentity( kalman-&amp;gt;error_cov_post,cvRealScalar(&lt;span style="color: maroon;"&gt;10&lt;/span&gt;) ); &lt;span style="color: green;"&gt;//large initial unknown&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: green;"&gt;//setup the initial state&lt;/span&gt;&lt;br /&gt;        cvmSet(kalman-&amp;gt;state_post,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;,initial_pos );&lt;br /&gt;        &lt;span style="color: blue;"&gt;if&lt;/span&gt; (m_order&amp;gt;&lt;span style="color: maroon;"&gt;1&lt;/span&gt;)&lt;br /&gt;            cvmSet(kalman-&amp;gt;state_post,&lt;span style="color: maroon;"&gt;1&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;,initial_vel);&lt;br /&gt;        &lt;span style="color: blue;"&gt;if&lt;/span&gt; (m_order&amp;gt;&lt;span style="color: maroon;"&gt;2&lt;/span&gt;)&lt;br /&gt;            cvmSet(kalman-&amp;gt;state_post,&lt;span style="color: maroon;"&gt;2&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;,initial_accel);&lt;br /&gt;        &lt;br /&gt;        &lt;br /&gt;    };&lt;br /&gt;    &lt;span style="color: blue;"&gt;void&lt;/span&gt; SetDT(&lt;span style="color: blue;"&gt;float&lt;/span&gt; dt) {&lt;br /&gt;        &lt;span style="color: green;"&gt;//3rd, 2nd, and 1st order transition matrix models&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: green;"&gt;//3rd order uses 2nd order leapfrog integration&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: blue;"&gt;float&lt;/span&gt; F3[] = {   &lt;span style="color: maroon;"&gt;1&lt;/span&gt;, dt, &lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.5&lt;/span&gt;*dt*dt,&lt;br /&gt;            &lt;span style="color: maroon;"&gt;0&lt;/span&gt;,  &lt;span style="color: maroon;"&gt;1&lt;/span&gt;, dt,&lt;br /&gt;            &lt;span style="color: maroon;"&gt;0&lt;/span&gt;,  &lt;span style="color: maroon;"&gt;0&lt;/span&gt;,  &lt;span style="color: maroon;"&gt;1&lt;/span&gt;};&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: blue;"&gt;float&lt;/span&gt; F2[] = {   &lt;span style="color: maroon;"&gt;1&lt;/span&gt;, dt, &lt;br /&gt;            &lt;span style="color: maroon;"&gt;0&lt;/span&gt;,  &lt;span style="color: maroon;"&gt;1&lt;/span&gt;};&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: blue;"&gt;float&lt;/span&gt; F1[] = {&lt;span style="color: maroon;"&gt;1&lt;/span&gt;};&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: blue;"&gt;switch&lt;/span&gt; (m_order) {&lt;br /&gt;            &lt;span style="color: blue;"&gt;case&lt;/span&gt; &lt;span style="color: maroon;"&gt;3&lt;/span&gt;:&lt;br /&gt;                memcpy( kalman-&amp;gt;transition_matrix-&amp;gt;data.fl, F3, &lt;span style="color: blue;"&gt;sizeof&lt;/span&gt;(F3));&lt;br /&gt;                &lt;span style="color: blue;"&gt;break&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: blue;"&gt;case&lt;/span&gt; &lt;span style="color: maroon;"&gt;2&lt;/span&gt;:&lt;br /&gt;                memcpy( kalman-&amp;gt;transition_matrix-&amp;gt;data.fl, F2, &lt;span style="color: blue;"&gt;sizeof&lt;/span&gt;(F2));&lt;br /&gt;                &lt;span style="color: blue;"&gt;break&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: blue;"&gt;case&lt;/span&gt; &lt;span style="color: maroon;"&gt;1&lt;/span&gt;:&lt;br /&gt;                memcpy( kalman-&amp;gt;transition_matrix-&amp;gt;data.fl, F1, &lt;span style="color: blue;"&gt;sizeof&lt;/span&gt;(F1));&lt;br /&gt;                &lt;span style="color: blue;"&gt;break&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: blue;"&gt;void&lt;/span&gt; SetMeasurements(&lt;span style="color: blue;"&gt;float&lt;/span&gt; pos, &lt;span style="color: blue;"&gt;float&lt;/span&gt; vel, &lt;span style="color: blue;"&gt;float&lt;/span&gt; accel) {&lt;br /&gt;        cvmSet(z,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;,pos);&lt;br /&gt;        &lt;span style="color: green;"&gt;//if (z-&amp;gt;rows&amp;gt;1)&lt;/span&gt;&lt;br /&gt;            cvmSet(z,&lt;span style="color: maroon;"&gt;1&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;,vel);&lt;br /&gt;        &lt;span style="color: green;"&gt;//if (z-&amp;gt;rows&amp;gt;2)&lt;/span&gt;&lt;br /&gt;            cvmSet(z,&lt;span style="color: maroon;"&gt;2&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;,accel);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    &lt;span style="color: blue;"&gt;void&lt;/span&gt; Update(){&lt;br /&gt;        &lt;span style="color: blue;"&gt;const&lt;/span&gt; CvMat* y = cvKalmanPredict( kalman, &lt;span style="color: maroon;"&gt;0&lt;/span&gt; );&lt;br /&gt;        cvKalmanCorrect( kalman, z );&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; GetPositionEstimate() {&lt;br /&gt;        &lt;span style="color: blue;"&gt;float&lt;/span&gt; v = cvmGet(kalman-&amp;gt;state_post,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;);&lt;br /&gt;        &lt;span style="color: blue;"&gt;return&lt;/span&gt; v;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; GetVelocityEstimate() {&lt;br /&gt;        &lt;span style="color: blue;"&gt;if&lt;/span&gt; (kalman-&amp;gt;state_post-&amp;gt;rows&amp;gt;&lt;span style="color: maroon;"&gt;1&lt;/span&gt;)&lt;br /&gt;            &lt;span style="color: blue;"&gt;return&lt;/span&gt; cvmGet(kalman-&amp;gt;state_post,&lt;span style="color: maroon;"&gt;1&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;);&lt;br /&gt;        &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: maroon;"&gt;0&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; GetAccelerationEstimate() {&lt;br /&gt;        &lt;span style="color: blue;"&gt;if&lt;/span&gt; (kalman-&amp;gt;state_post-&amp;gt;rows&amp;gt;&lt;span style="color: maroon;"&gt;2&lt;/span&gt;)&lt;br /&gt;            &lt;span style="color: blue;"&gt;return&lt;/span&gt; cvmGet(kalman-&amp;gt;state_post,&lt;span style="color: maroon;"&gt;2&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;);&lt;br /&gt;        &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: maroon;"&gt;0&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; GetPositionError() {&lt;br /&gt;        &lt;span style="color: blue;"&gt;return&lt;/span&gt; cvmGet(kalman-&amp;gt;error_cov_post,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;    CvKalman* kalman; &lt;span style="color: green;"&gt;//openCV Kalman filter&lt;/span&gt;&lt;br /&gt;    CvMat* z; &lt;span style="color: green;"&gt;//measurement matrix&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;void&lt;/span&gt; cvKalmanNoObservation() { &lt;br /&gt;        cvCopy(kalman-&amp;gt;error_cov_pre, kalman-&amp;gt;error_cov_post); &lt;br /&gt;        cvCopy(kalman-&amp;gt;state_pre, kalman-&amp;gt;state_post); &lt;br /&gt;    } &lt;br /&gt;    &lt;span style="color: blue;"&gt;int&lt;/span&gt; m_order;&lt;br /&gt;    &lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;#endif&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-3663710003101885918?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/3663710003101885918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=3663710003101885918' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3663710003101885918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3663710003101885918'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/08/kalman-filters-part-2.html' title='Kalman filters - Part 2'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/THUdr8X54QI/AAAAAAAAATE/_J7tC3pmA9A/s72-c/eqn2375.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-923348694388434696</id><published>2010-08-17T15:24:00.001+08:00</published><updated>2010-08-17T15:49:21.225+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><title type='text'>CAD packages</title><content type='html'>Some basic knowledge of CAD packages never hurt anyone. Two of the most common ones used in industry are &lt;a href="http://www.autodesk.com/"&gt;AutoCAD&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Solid_Edge"&gt;SolidEdge&lt;/a&gt;. Most of the time you will just need to take measurements from some diagrams rather than build a complete model.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TGo42QboeZI/AAAAAAAAASs/pRP5IzFKztg/s1600/autocad_extend.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TGo42QboeZI/AAAAAAAAASs/pRP5IzFKztg/s320/autocad_extend.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;AutoCAD has a command line interface (from way back in the DOS days). Two useful commands for measurement are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;di - Measure a distance between two points&lt;/li&gt;&lt;li&gt;id - Print the coordinates of a point of interest&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Other things you might find yourself doing include drawing lines and circles, which are all relatively self-explanatory. Occasionally you need to measure something relative to a reference line or base line that you want to project through the whole drawing. You can do this by using the 'extend' option to lengthen the line. Simply choose the 'Extend' option from the modify menu and draw a line to represent the boundary of the lines extension, right click, and select the line you wish to lengthen. AutoCAD will lengthen the selected line up to the boundary you specified.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TGo-6mr71QI/AAAAAAAAAS8/O6K9yOP9UJc/s1600/autocad-layer.PNG" imageanchor="1" style="clear: right; cssfloat: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" ox="true" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TGo-6mr71QI/AAAAAAAAAS8/O6K9yOP9UJc/s320/autocad-layer.PNG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Like Photoshop AutoCAD also has layers which you can work with. You can turn layers on/off by clicking on the lightbulb function.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TGo4_0lvtHI/AAAAAAAAAS0/MU-Y-MWIxt4/s1600/solid_edge-distance.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TGo4_0lvtHI/AAAAAAAAAS0/MU-Y-MWIxt4/s320/solid_edge-distance.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;With SolidEdge you can use the dimension menu to make measurements (Make sure you are working on the correct sheet!). These can be either horizontal/vertical, by two points, or you can select an element in the drawing to use as the axis (easier than in Autocad!).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-923348694388434696?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/923348694388434696/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=923348694388434696' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/923348694388434696'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/923348694388434696'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/08/cad-packages.html' title='CAD packages'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nHcDA3NyAms/TGo42QboeZI/AAAAAAAAASs/pRP5IzFKztg/s72-c/autocad_extend.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-6223139376892054693</id><published>2010-08-06T20:59:00.000+08:00</published><updated>2010-08-06T20:59:18.757+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='education'/><category scheme='http://www.blogger.com/atom/ns#' term='GPGPU'/><title type='text'>Computing events in Perth</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TFwHE9FvG2I/AAAAAAAAASk/xWT80bQH0W8/s1600/original.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TFwHE9FvG2I/AAAAAAAAASk/xWT80bQH0W8/s320/original.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://gamejam.org/"&gt;GameJam&lt;/a&gt; is on again in Perth - I didn't see much about it this time, but it is in Joondalup again. Also, there is a GPU computing workshop on the 19th of August in the ARRC auditorium. More information on the workshop is available &lt;a href="http://local.wasp.uwa.edu.au/data/GPU_Workshop.pdf"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-6223139376892054693?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/6223139376892054693/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=6223139376892054693' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6223139376892054693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6223139376892054693'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/08/computing-events-in-perth.html' title='Computing events in Perth'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nHcDA3NyAms/TFwHE9FvG2I/AAAAAAAAASk/xWT80bQH0W8/s72-c/original.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-6855190479289574511</id><published>2010-08-05T20:09:00.002+08:00</published><updated>2010-08-06T20:37:41.421+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>A star (A*) pathplanning</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TFv-SbUAEEI/AAAAAAAAASc/dTPPxhJh4os/s1600/aStarT6.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TFv-SbUAEEI/AAAAAAAAASc/dTPPxhJh4os/s320/aStarT6.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;Previously I wrote about Dijkstra, this time I'm going to look at heuristic or "AI" style approach the A* algorithm. This is a single-source single-goal pathfinding algorithm. In essence this algorithm "guesses" or estimates the distance that remain to get from a node to the destination node. These estimates guide the direction of the path (i.e. search), with each node that is visited updating the true cost of the path, until a solution is found.&lt;br /&gt;&lt;br /&gt;A* considers what to do at each node depending on an overall heuristic score. The total score is a function of the cost of the path that has already been traversed (the "g" cost) and the estimated cost of traveling from the node to the destination (the "h" cost). There are many ways to estimate the "h" cost, typically for pathfinding problems the euclidian distance is used, however it is always better to over-estimate the remaining cost (so you will explore more feasible solutions), and so a common measure used is the &lt;a href="http://en.wikipedia.org/wiki/Taxicab_geometry"&gt;manhattan distance&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The A* algorithm works on two lists, a "Closed" list of already explored nodes, and an "Open" list of nodes yet-to-be-explored.&lt;br /&gt;&lt;br /&gt;In essence the algorithm is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Select a source node to operate with (eg: the start node, or the node with the lowest overall cost)&lt;br /&gt;&lt;li&gt;For each node connected to the source node:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Calculate the already-traveresed cost&lt;br /&gt;&lt;li&gt;If the node is on the closed list, and the newly calculated traversed cost exceeds the existing traversed cost for the node, skip the node, otherwise remove it from closed.&lt;br /&gt;&lt;li&gt; Calculate the estimate cost to find the total cost, and store all these costs with the node.&lt;br /&gt;&lt;li&gt;Add the node to the Open list&lt;br /&gt;&lt;/ul&gt;&lt;li&gt;Add the source node to the Closed list&lt;br /&gt;&lt;/ul&gt;In Pseudo-Code (from Bryan Stout):&lt;pre&gt;priorityqueue Open&lt;br /&gt; list Closed &lt;br /&gt;s.g = 0 // s is the start node &lt;br /&gt;s.h = GoalDistEstimate( s ) &lt;br /&gt;s.f = s.g + s.h &lt;br /&gt;s.parent = null &lt;br /&gt;push s on Open &lt;br /&gt;while Open is not empty &lt;br /&gt;  pop node n from Open // n has the lowest f &lt;br /&gt;  if n is a goal node &lt;br /&gt;    construct path &lt;br /&gt;    return success &lt;br /&gt;  for each successor n' of n &lt;br /&gt;    newg = n.g + cost(n,n') &lt;br /&gt;    if n' is in Open or Closed, and n'.g &lt; = newg &lt;br /&gt;      skip &lt;br /&gt;    n'.parent = n &lt;br /&gt;    n'.g = newg &lt;br /&gt;    n'.h = GoalDistEstimate( n' ) &lt;br /&gt;    n'.f = n'.g + n'.h &lt;br /&gt;    if n' is in Closed &lt;br /&gt;      remove it from Closed &lt;br /&gt;    if n' is not yet in Open &lt;br /&gt;      push n' on Open &lt;br /&gt;  push n onto Closed &lt;br /&gt;return failure // if no path found &lt;br /&gt;&lt;/pre&gt;A great interactive demonstration program can be found here: &lt;a href="http://www.policyalmanac.org/games/aStarTutorial.htm"&gt;http://www.policyalmanac.org/games/aStarTutorial.htm&lt;/a&gt;  And some &lt;a href="http://www.grinninglizard.com/MicroPather/"&gt;source code for A* is available from the GrinningLizard website&lt;/a&gt; (The same author as the fantastic &lt;a href="http://www.grinninglizard.com/tinyxml/"&gt;tinyXML library&lt;/a&gt;!)  Keep in mind that waypoint-based AI navigation for games is a very mid-nineties approach, nav-mesh's are certainly the way to go! For an example of issues with waypoint approaches take a look at this video:&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/lw9G-8gL5o0&amp;amp;hl=en_US&amp;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/lw9G-8gL5o0&amp;amp;hl=en_US&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;Your best bet for &lt;a href="http://digestingduck.blogspot.com/"&gt;navmesh research is Mikko Mononen's blog&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-6855190479289574511?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/6855190479289574511/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=6855190479289574511' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6855190479289574511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6855190479289574511'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/08/star-pathplanning.html' title='A star (A*) pathplanning'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_nHcDA3NyAms/TFv-SbUAEEI/AAAAAAAAASc/dTPPxhJh4os/s72-c/aStarT6.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-8570898957348205170</id><published>2010-08-04T19:53:00.001+08:00</published><updated>2010-08-06T20:08:28.143+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='GPGPU'/><title type='text'>Using Parallel Reduction to Optimize Dijkstra</title><content type='html'>In a previous blog post I wrote about Dijkstra's algorithm. One optimisation to the naive implementation is to calculate the minimum cost node in parallel - since this can often be the most time consuming operation for large graphs. This is a perfect candidate for a parallel reduction operation. &lt;br /&gt;&lt;br /&gt;In serial, if we wished to sum up an array (x) of numbers, the code would be:&lt;br /&gt;&lt;pre&gt;int sum = 0;&lt;br /&gt;for(int i=0; i &amp;lt; N; ++i) &lt;br /&gt; sum += x[i];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;However, in parallel we could speed this up by summing parts of the array and then adding those parts together. For example, to add four numbers a,b,c,d we could first add a+b and c+d in parallel, then sum ab+cd. This is called a 'reduction' operation, and it allows us to complete an otherwise O(N) operation in O(log(N)) steps.&lt;br /&gt;&lt;br /&gt;One particularly nifty pattern is the "Butterfly" pattern of adding elements. Best described with an animation:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TFv5CwQGFHI/AAAAAAAAASU/jHWxX3JE7BA/s1600/butterfly.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TFv5CwQGFHI/AAAAAAAAASU/jHWxX3JE7BA/s320/butterfly.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;In code this can be done as:&lt;br /&gt;&lt;pre&gt;&lt;span style=' color: Blue;'&gt;for&lt;/span&gt; (b=n/&lt;span style=' color: Maroon;'&gt;2&lt;/span&gt;;b&amp;gt;&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;;b/=&lt;span style=' color: Maroon;'&gt;2&lt;/span&gt;) {&lt;br /&gt; &lt;span style=' color: Blue;'&gt;for&lt;/span&gt; (i=&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;;i&amp;lt;n;i++) { &lt;br /&gt;         t[i] = OP(sum[i],sum[i^b]); &lt;br /&gt; } &lt;br /&gt; &lt;span style=' color: Blue;'&gt;for&lt;/span&gt; (i=&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;;i&amp;lt;n;i++) { &lt;br /&gt;         sum[i]=t[i]; &lt;br /&gt; } &lt;br /&gt;}&lt;/pre&gt;(Where 'OP' can be any serial commutative operation, e.g. add, subtract, etc.)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To see how this works assume we are adding 8 elements (n=8) then for the first step:&lt;br /&gt;b is 0100&lt;br /&gt;and each subsequent operation will be operating on the following elements:&lt;br /&gt;&lt;pre&gt;0000^0100:0100&lt;br /&gt;0001^0100:0101&lt;br /&gt;0010^0100:0110&lt;br /&gt;0011^0100:0111&lt;br /&gt;0100^0100:0000&lt;br /&gt;0101^0100:0001&lt;br /&gt;0110^0100:0010&lt;br /&gt;0111^0100:0011&lt;br /&gt;&lt;/pre&gt;or in decimal:&lt;br /&gt;&lt;pre&gt;t[0] = [0] + [4]&lt;br /&gt;t[1] = [1] + [5] &lt;br /&gt;t[2] = [2] + [6]&lt;br /&gt;t[3] = [3] + [7]&lt;br /&gt;t[4] = [4] + [0]&lt;br /&gt;t[5] = [5] + [1]&lt;br /&gt;t[6] = [6] + [2]&lt;br /&gt;t[7] = [7] + [3]&lt;br /&gt;&lt;/pre&gt;Now, for the next step:&lt;br /&gt;b is 0010&lt;br /&gt;&lt;pre&gt;0000^0010:0010&lt;br /&gt;0001^0010:0011&lt;br /&gt;0010^0010:0000&lt;br /&gt;0011^0010:0001&lt;br /&gt;0100^0010:0110&lt;br /&gt;0101^0010:0111&lt;br /&gt;0110^0010:0100&lt;br /&gt;0111^0010:0101&lt;br /&gt;&lt;/pre&gt;Again, in decimal:&lt;br /&gt;&lt;pre&gt;t[0] = [0] + [2]&lt;br /&gt;t[1] = [1] + [3]&lt;br /&gt;t[2] = [2] + [0]&lt;br /&gt;t[3] = [3] + [1]&lt;br /&gt;t[4] = [4] + [6]&lt;br /&gt;t[5] = [5] + [7]&lt;br /&gt;t[6] = [6] + [4]&lt;br /&gt;t[7] = [7] + [5]&lt;br /&gt;&lt;/pre&gt;Finally,&lt;br /&gt;b is 0001&lt;br /&gt;&lt;pre&gt;0000^0001:0001&lt;br /&gt;0001^0001:0000&lt;br /&gt;0010^0001:0011&lt;br /&gt;0011^0001:0010&lt;br /&gt;0100^0001:0101&lt;br /&gt;0101^0001:0100&lt;br /&gt;0110^0001:0111&lt;br /&gt;0111^0001:0110&lt;br /&gt;&lt;/pre&gt;And in decimal:&lt;br /&gt;&lt;pre&gt;t[0] = [0] + [1]&lt;br /&gt;t[1] = [1] + [0]&lt;br /&gt;t[2] = [2] + [3]&lt;br /&gt;t[3] = [3] + [2]&lt;br /&gt;t[4] = [4] + [5]&lt;br /&gt;t[5] = [5] + [4]&lt;br /&gt;t[6] = [6] + [7]&lt;br /&gt;t[7] = [7] + [6]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Thus, in only 3 parallel operations we have added 8 elements together. We also have the additional bonus of having broadcast the result to all of the eight parallel adding elements - allowing future operations for each processor to use the result, or in the case of a SIMD system, to mask the appropriate processors.&lt;br /&gt;&lt;br /&gt;Here is the code in CUDA:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; i = threadIdx.x; &lt;span style=' color: Green;'&gt;// Thread i holds value x_i, one thread per element&lt;/span&gt;&lt;br /&gt; __shared__ &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; sum[blocksize]; &lt;br /&gt;sum[i] = x_i; &lt;span style=' color: Green;'&gt;//copy to shared memory&lt;/span&gt; &lt;br /&gt;__syncthreads(); &lt;span style=' color: Green;'&gt;//synchronise&lt;/span&gt; &lt;br /&gt;&lt;span style=' color: Blue;'&gt;for&lt;/span&gt;(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; bit=blocksize/&lt;span style=' color: Maroon;'&gt;2&lt;/span&gt;; bit&amp;gt;&lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;; bit/=&lt;span style=' color: Maroon;'&gt;2&lt;/span&gt;) {&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; t=OP(sum[i],sum[i^bit]);  &lt;br /&gt;    __syncthreads(); &lt;br /&gt;    sum[i]=t;  &lt;br /&gt;    __syncthreads(); &lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Nifty!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-8570898957348205170?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/8570898957348205170/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=8570898957348205170' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8570898957348205170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8570898957348205170'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/08/using-parallel-reduction-to-optimize.html' title='Using Parallel Reduction to Optimize Dijkstra'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_nHcDA3NyAms/TFv5CwQGFHI/AAAAAAAAASU/jHWxX3JE7BA/s72-c/butterfly.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-8123282053482075017</id><published>2010-08-03T17:48:00.005+08:00</published><updated>2010-08-04T18:02:18.428+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Dijkstra</title><content type='html'>Dijkstra's algorithm is a well known algorithm for solving the single-source shortest path problem in a graph. It is a "global" pathfinding algorithm, in that it will find the optimal solution to all the other nodes in the graph (provided the graph has no negative cost edges or cycles). Unfortunately the algorithm is not very easy to run in parallel.&lt;br /&gt;&lt;br /&gt;The algorithm requires two lists, a visited list, and a pending list, and an array of the current distances to each node, plus the precursors. &lt;br /&gt;&lt;br /&gt;In essence the algorithm begins at a starting node, and all other nodes are added to a 'pending' list. The distances are initialised to 'infinite'. We begin at the starting node that has been specified.&lt;br /&gt;&lt;br /&gt;1. From this node we calculate the distance to each neighbouring node. If the distance is less than the current record, we update the distance measurement (cost of getting to current node plus cost to get to neighbour node), and update the precursor to the neighbour node to be the present node.&lt;br /&gt;&lt;br /&gt;2. From all nodes, the node with the minimum distance on the pending list is selected as the next node to visit. This new node is then added to the visited list and removed from the pending list..&lt;br /&gt;&lt;br /&gt;It's quite simple, but an animation will really help get the point across:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/TFk4m-1Zj4I/AAAAAAAAASM/i_1BnbRQm0E/s1600/dijkstra.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="300" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TFk4m-1Zj4I/AAAAAAAAASM/i_1BnbRQm0E/s400/dijkstra.gif" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;In code, the algorithm is as follows:&lt;br /&gt;(This code stores the graph in the "dist" array, with dist[i][j] representing an edge cost between i and j. If it contains '0' then there is no connection). &lt;br /&gt;&lt;br /&gt;The initial loop sets the distances to infinity. The first inner loop finds the minimum cost node, the second inner loop updates the distances based on the current node.&lt;br /&gt;The minimum distance to each node from the starting node is stored in the 'd' array. The visited array is used to record which nodes have already been processed.&lt;br /&gt;&lt;pre&gt;&lt;span style=' color: Blue;'&gt;void&lt;/span&gt; dijkstra(&lt;span style=' color: Blue;'&gt;int&lt;/span&gt; s) {        &lt;br /&gt;    &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; i, k, mini;         &lt;br /&gt;    &lt;span style=' color: Blue;'&gt;int&lt;/span&gt; visited[GRAPHSIZE];         &lt;br /&gt;&lt;span style=' color: Green;'&gt;//initialize all distances to infinite, and set the visited nodes to none.              &lt;/span&gt;&lt;br /&gt;    &lt;span style=' color: Blue;'&gt;for&lt;/span&gt; (i = &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;; i &amp;lt;= n; ++i) { &lt;br /&gt;     d[i] = INFINITY; visited[i] = &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;; &lt;br /&gt;    }         &lt;br /&gt;&lt;span style=' color: Green;'&gt;//set the distance to the starting node 's' to zero&lt;/span&gt; &lt;br /&gt;    d[s] = &lt;span style=' color: Maroon;'&gt;0&lt;/span&gt;; &lt;br /&gt;&lt;span style=' color: Green;'&gt;//outer loop - iterate through all nodes&lt;/span&gt; &lt;br /&gt;    &lt;span style=' color: Blue;'&gt;for&lt;/span&gt; (k = &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;; k &amp;lt;= n; ++k) {                &lt;br /&gt;&lt;span style=' color: Green;'&gt;//find the minimum cost node&lt;/span&gt; &lt;br /&gt;&lt;span style=' color: Green;'&gt;//if the node has not been visited, and the minimum cost node is not initialised, &lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Green;'&gt;//then set the minimum cost node to the current node&lt;/span&gt; &lt;br /&gt;&lt;span style=' color: Green;'&gt;//if the distance to the current node is less than the current minimum,&lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Green;'&gt;//then update the minimum&lt;/span&gt; &lt;br /&gt;     mini = -&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;;                 &lt;br /&gt;     &lt;span style=' color: Blue;'&gt;for&lt;/span&gt; (i = &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;; i &amp;lt;= n; ++i)                      &lt;br /&gt;          &lt;span style=' color: Blue;'&gt;if&lt;/span&gt; (!visited[i]&amp;amp;&amp;amp;((mini==-&lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;)||(d[i]&amp;lt;[mini])))                                        &lt;br /&gt;          mini = i; &lt;br /&gt;&lt;span style=' color: Green;'&gt;//now we have the current minimum node, set it to visited&lt;/span&gt; &lt;br /&gt;     visited[mini] = &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;; &lt;span style=' color: Green;'&gt;//visit node               &lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Green;'&gt;//for each node, if there is a valid edge between the current minimum node &lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Green;'&gt;//then calculate the cost to visit this neighbour node via the current node.&lt;/span&gt;&lt;br /&gt;&lt;span style=' color: Green;'&gt;//if the cost is less than the current record of minimum costs, update the minimum cost.&lt;/span&gt;&lt;br /&gt;     &lt;span style=' color: Blue;'&gt;for&lt;/span&gt; (i = &lt;span style=' color: Maroon;'&gt;1&lt;/span&gt;; i &amp;lt;= n; ++i)                               &lt;br /&gt;        &lt;span style=' color: Blue;'&gt;if&lt;/span&gt; (dist[mini][i]) &lt;span style=' color: Green;'&gt;//update distances                                    &lt;/span&gt;&lt;br /&gt;        &lt;span style=' color: Blue;'&gt;if&lt;/span&gt; (d[mini] + dist[mini][i] &amp;lt; d[i])                                                        &lt;br /&gt;              d[i] = d[mini] + dist[mini][i];         &lt;br /&gt;    } &lt;br /&gt;}&lt;/pre&gt;In future blog posts I'll look at the A* algorithm, a parallel reduction for Dijkstra and some SIMD/GPU/CUDA optimisations for an 8-connected Dijkstra.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-8123282053482075017?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/8123282053482075017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=8123282053482075017' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8123282053482075017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8123282053482075017'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/08/dijkstra.html' title='Dijkstra'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/TFk4m-1Zj4I/AAAAAAAAASM/i_1BnbRQm0E/s72-c/dijkstra.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-7518819906732498106</id><published>2010-08-02T08:45:00.023+08:00</published><updated>2010-08-04T09:19:47.210+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='compilers'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>C++ debugging tools: Gdb, CppCheck, Valgrind</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/TFjAKRocShI/AAAAAAAAASE/NX1tRhGNkG8/s1600/valgrind.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="83" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TFjAKRocShI/AAAAAAAAASE/NX1tRhGNkG8/s200/valgrind.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;One of the most important parts of programming is the debugging phase, and for development, the testing phase. Some of the tools that can be used under OSX are the standard linux tools - but ofcourse, there are always a few tweeks.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=Main_Page"&gt;CppCheck&lt;/a&gt; is a static analysis tool, it can find formatting issues, unused variables or sub-optimally used variables, pointer/memory issues, etc.&lt;br /&gt;&lt;br /&gt;The install procedure for CppCheck is:&lt;br /&gt;&lt;pre&gt;git clone git://github.com/danmar/cppcheck.git&lt;br /&gt;make&lt;br /&gt;sudo make install&lt;br /&gt;&lt;br /&gt;sudo easy_install Pygments-1.3.1-py2.6.egg &lt;br /&gt;http://pypi.python.org/pypi/Pygments&lt;br /&gt;&lt;br /&gt;cd htmlreport&lt;br /&gt;sudo ./setup.py install&lt;br /&gt;&lt;/pre&gt;(The python aspect you only need for a nice html report)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Note, I had to check out v 1.44 for it to work with OSX, so after the git checkout command add the following:&lt;br /&gt;&lt;pre&gt;git checkout 1.44&lt;br /&gt;git checkout -b 144&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here is an example shell script to run cpp-check (thanks John):&lt;br /&gt;&lt;pre&gt;#!/bin/bash&lt;br /&gt;cppcheck --enable=all --xml --verbose -f -I math -I boost/boost -I src/framework src 2&amp;gt; err.xml&lt;br /&gt;cppcheck-htmlreport --file err.xml --report-dir="CodeAnalysisReport" --title="My Project"&lt;br /&gt;&lt;/pre&gt;Just alter it to match your own include directories and source.&lt;br /&gt;&lt;br /&gt;If you need to do any runtime debugging, GDB is the standard tool. It can be quite complex, but here is its basic usage:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; gdb (program name) [this will start GDB with your program loaded]&lt;br /&gt;&lt;/li&gt;&lt;li&gt; set args (arguments) [this will set the command line parameters to your program]&lt;br /&gt;&lt;/li&gt;&lt;li&gt; break (function/bp) [eg: break lib/preprocessor.cpp:610]&lt;br /&gt;&lt;/li&gt;&lt;li&gt; r [run]&lt;br /&gt;&lt;/li&gt;&lt;li&gt; bt [trace]&lt;br /&gt;&lt;/li&gt;&lt;li&gt; q [quit]&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Not as good as the MS debug tools, but its still far better than not having a debugger at all!  Finally, &lt;a href="http://valgrind.org/"&gt;Valgrind&lt;/a&gt; is a tool for memory-checking. It normally works out of the box, but I had to make some changes for OSX. Luckily Greg Parker already wrote a patch, and  &lt;a href="http://blog.loudhush.ro/2010/02/compiling-valgrind-on-snow-leopard.html"&gt; Cristian Draghici wrote up a blog post on compiling and installing valgrind on OSX&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-7518819906732498106?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/7518819906732498106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=7518819906732498106' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7518819906732498106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7518819906732498106'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/08/c-debugging-tools-gdb-cppcheck-valgrind.html' title='C++ debugging tools: Gdb, CppCheck, Valgrind'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/TFjAKRocShI/AAAAAAAAASE/NX1tRhGNkG8/s72-c/valgrind.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-3253091022906027741</id><published>2010-07-27T18:27:00.000+08:00</published><updated>2010-07-27T18:27:33.231+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='magic2010'/><title type='text'>WAMBOT makes it into the Finals!</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TE6asdtp3kI/AAAAAAAAARs/N-OK70D6A2Q/s1600/wambot-team-prep.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="212" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TE6asdtp3kI/AAAAAAAAARs/N-OK70D6A2Q/s320/wambot-team-prep.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&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;/div&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/TE6cE1JzAfI/AAAAAAAAAR0/V4JOJ2UAxKI/s1600/wambot-team-thinking.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/TE6cE1JzAfI/AAAAAAAAAR0/V4JOJ2UAxKI/s320/wambot-team-thinking.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;Just got off the plane from Europe, and I'm ecstatic to say that our team MAGICIAN / &lt;a href="http://www.wambot.org/"&gt;WAMBOT&lt;/a&gt; has made it as one of the &lt;a href="http://www.defence.gov.au/media/DepartmentalTpl.cfm?CurrentId=10654"&gt;six finalists&lt;/a&gt; for the MAGIC 2010 competition. Our success will help put Perth, Western Australia on the map as a place for robotics research. ECU, UWA and Thales put together a massive engineering effort to complete the robots and we had strong support from our sponsors Thales, SICK, XSens, RTI, and plenty of help from Illiarc. DSTO has allowed us to release photos of the robots and the event now, so I'm glad to be able to share some pictures of the action.&lt;br /&gt;&lt;br /&gt;If you see any news stories on the event or would like to help our team - don't hesitate to leave a comment below!&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TE60HWJY-8I/AAAAAAAAAR8/k1KhK_Uh-50/s1600/boeingbraunl.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TE60HWJY-8I/AAAAAAAAAR8/k1KhK_Uh-50/s320/boeingbraunl.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;Go Team &lt;a href="http://www.wambot.org/"&gt;WAMBOT&lt;/a&gt;! &lt;br /&gt;&lt;br /&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;/div&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TE6ajtIzaqI/AAAAAAAAARk/JY83c0yMZTQ/s1600/wambot-robots.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TE6ajtIzaqI/AAAAAAAAARk/JY83c0yMZTQ/s320/wambot-robots.jpg" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-3253091022906027741?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/3253091022906027741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=3253091022906027741' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3253091022906027741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3253091022906027741'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/07/wambot-makes-it-into-finals.html' title='WAMBOT makes it into the Finals!'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_nHcDA3NyAms/TE6asdtp3kI/AAAAAAAAARs/N-OK70D6A2Q/s72-c/wambot-team-prep.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-6661475937532152687</id><published>2010-06-14T16:22:00.002+08:00</published><updated>2010-06-14T16:43:15.089+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='computers'/><title type='text'>Customising Access to Windows XP</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/TBXmjyKuA4I/AAAAAAAAARc/nWGcphmbYSw/s1600/windows_xp_logo.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_nHcDA3NyAms/TBXmjyKuA4I/AAAAAAAAARc/nWGcphmbYSw/s320/windows_xp_logo.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;Delivering a Windows XP system to a customer, and don't want them to fiddle with settings?&lt;br /&gt;&lt;br /&gt;First, you probably want to have your system log on automatically.&lt;br /&gt;The &lt;a href="http://support.microsoft.com/kb/315231"&gt;Microsoft article on enabling autologin&lt;/a&gt; goes through the steps in detail. Essentially, start regedit and set HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon AutoAdminLogon (SZ) to 1.&lt;br /&gt;&lt;br /&gt;Then add whatever you want on startup to the start menu 'Startup' folder. (Documents and Settings\USERNAME\Start Menu\Programs\Startup) &lt;br /&gt;&lt;br /&gt;This is also a good time to clear the startup menu of any other pesky programs. To eliminate system wide startup items easily you can try MSConfig (from run), but I prefer to edit the registry directly.&lt;br /&gt;Check HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run and RunOnce and RunOnceEx. If you just want to eliminate the taskbar icons all together you can try editing HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer and add a DWORD NoTrayItemsDisplay and set it to 1. &lt;br /&gt;&lt;br /&gt;You can disable the windows keys etc using HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout\Scancode Map&lt;br /&gt;For a detailed discussion see &lt;a href="http://www.northcode.com/blog.php/2007/07/25/Securing-Windows-For-Use-As-A-Kiosk"&gt;Tim's Northcode blog post&lt;/a&gt;, who suggests "Scancode Map"=hex:00,00,00,00,00,00,00,00,09,00,00,00,00,00,5b,e0,00,00,5c,e0,00,00,5d,e0,00,00, 44,00,00,00,1d,00,00,00,38,00,00,00,1d,e0,00,00,38,e0,00,00,00,00.&lt;br /&gt;&lt;br /&gt;Note that this stops you from being able to use any of the windows special keys. So be careful!&lt;br /&gt;&lt;br /&gt;Finally you want to lock down the user access rights. There are many ways to do this, the easiest is with the Group Policy editor. This &lt;a href="http://support.microsoft.com/kb/307882"&gt;Microsoft article on the Group Policy Editor&lt;/a&gt; describes how to get there, in essence: Start,run,MMC,Add a snap-in,'Group Policy Object Editor'.&lt;br /&gt;&lt;br /&gt;Now you have options to edit under "User Configuration" and "Administrative Templates". Under "Start Menu and Taskbar" you can find options to disable Search, Help, etc. from the start menu. Under "Desktop" you can remove the various icons, and disable the desktop. Under "System" you can set which programs people can run. You might want to be careful not to disable regedit until you are 100% certain it is correctly setup.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-6661475937532152687?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/6661475937532152687/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=6661475937532152687' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6661475937532152687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6661475937532152687'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/06/customising-access-to-windows-xp.html' title='Customising Access to Windows XP'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nHcDA3NyAms/TBXmjyKuA4I/AAAAAAAAARc/nWGcphmbYSw/s72-c/windows_xp_logo.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-235415539938997817</id><published>2010-06-11T21:22:00.000+08:00</published><updated>2010-06-11T21:22:49.036+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='magic2010'/><title type='text'>Magic 2010</title><content type='html'>Our June MAGIC 2010 TAP is over, and I'm very proud of &lt;a href="http://www.wambot.org/"&gt;my team's&lt;/a&gt; performance. They put in a massive effort for the site-visit.&lt;br /&gt;&lt;br /&gt;Now time for normal life to resume, and some more regular blog posts... Right after I finish tying off the loose ends.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-235415539938997817?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/235415539938997817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=235415539938997817' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/235415539938997817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/235415539938997817'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/06/magic-2010.html' title='Magic 2010'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-3998957714393672401</id><published>2010-06-04T11:22:00.000+08:00</published><updated>2010-06-04T11:22:27.327+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>BZR on Windows</title><content type='html'>There are a number of source code control options, popular ones include &lt;a href="http://subversion.tigris.org/"&gt;subversion (SVN)&lt;/a&gt; and &lt;a href="http://git-scm.com/"&gt;GIT&lt;/a&gt;. CVS is on its way out. Python advocates prefer 'Bazaar' (BZR), which of course is a total pain to install on Windows.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/TAhxWN5zwpI/AAAAAAAAARU/6KZBjm_rGHQ/s1600/bazaar-logo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_nHcDA3NyAms/TAhxWN5zwpI/AAAAAAAAARU/6KZBjm_rGHQ/s320/bazaar-logo.png" /&gt;&lt;/a&gt;&lt;/div&gt;The steps are vaguely:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Install python (I used 2.6, pretty straight forward, run an exe)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Install &lt;a href="http://www.voidspace.org.uk/python/modules.shtml#pycrypto"&gt;py-crypto&lt;/a&gt; - you need this for ssh/sftp (Again, just an exe install not too painful, just choose the right one)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Install &lt;a href="http://www.lag.net/paramiko/"&gt;paramiko&lt;/a&gt;, this is the SSH client. Once again, just an exe for the ctypes support, and a python module. Again, choose the one that matches your python version.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Now get &lt;a href="http://wiki.bazaar.canonical.com/WindowsInstall"&gt;bzr&lt;/a&gt; and install it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Finally, add the python scripts to your path (advanced environment variables), and your ready to use BZR from the command prompt - still no gui!&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Compared to the simple install, setup and use procedure for SVN I can see why Bazaar isn't a popular choice. I've not tried GIT, but I'd suggest trying GIT over BZR for a distributed versioning system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-3998957714393672401?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/3998957714393672401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=3998957714393672401' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3998957714393672401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3998957714393672401'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/06/bzr-on-windows.html' title='BZR on Windows'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nHcDA3NyAms/TAhxWN5zwpI/AAAAAAAAARU/6KZBjm_rGHQ/s72-c/bazaar-logo.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-287674386249613180</id><published>2010-05-26T21:01:00.001+08:00</published><updated>2010-05-26T22:29:11.855+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='computers'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><title type='text'>Consumer Camera Streaming</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/S_0bc7wFgdI/AAAAAAAAARE/ygwG-8AEIrU/s1600/PSRemote+Pro1.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_nHcDA3NyAms/S_0bc7wFgdI/AAAAAAAAARE/ygwG-8AEIrU/s320/PSRemote+Pro1.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;I've been looking for a decent cheap camera for a long time. Hooking into a consumer Camera is apparently close to impossible. This used to be a simple and common tasks. Almost all digital camcorders used to provide firewire ports and would feature a demo mode allowing you to get a cheap high-quality video stream for your PC. Firewire now has been abandoned, and for a while camera manufacturers (in particular Sony) provided USB streaming. This is now a thing of the past.&lt;br /&gt;&lt;br /&gt;One alternative is to use a standard digital camera. Again, previously Cannon provided good support for remote capture and USB streaming, but this is something they seem to have dropped again.&lt;br /&gt;&lt;br /&gt;There are a few options out there for those who are looking for tethered camera capturing via USB:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://chdk.wikia.com/wiki/CHDK"&gt;CHDK&lt;/a&gt; the Cannon Hack Development Kit supports a number of cannon cameras with a range of possible features. Again, difficult to find support for a current model.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.breezesys.com/PSRemote/"&gt;BreezeSys&lt;/a&gt; provide a number of software tools for Cannon cameras, again only older models but if your really looking to do some specialized setup then this might be worth the effort.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.usa.canon.com/consumer/controller?act=SDKHomePageAct&amp;amp;keycode=Sdk_Lic&amp;amp;fcategoryid=314&amp;amp;modelid=7474&amp;amp;id=3464#SDKQ3"&gt;Canon Official Camera SDK&lt;/a&gt; is a good option, but unfortunately only the older models are supported. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.olympus.com/cameras.html"&gt;Olympus SDK&lt;/a&gt; supports a good range of cameras, unfortunately the only currently supported cameras are the more expensive DSLR range.&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.pinetreecomputing.com/camctl.asp"&gt;Pine Tree Camera Controller&lt;/a&gt; is a Windows GUI for the Olympus interface.&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.nikondigital.com/Find-Your-Nikon/Product/Imaging-Software/25366/Camera-Control-Pro-2.html"&gt;Nikon Camera Control&lt;/a&gt; (Windows) provides tethered control for Nikon DSLR cameras. (See also &lt;a href="http://www.diyphotobits.com/download-diyphotobitscom-camera-control/"&gt;DIY Nikon&lt;/a&gt;)&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.sofortbildapp.com/"&gt;SofortBuild&lt;/a&gt; is Mac OSX software for remote capture with Nikon cameras, but unfortunately only for the more expensive "D" series.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.gphoto.org/"&gt;GPhoto&lt;/a&gt; is some linux software for remote capture from a wide range of Cameras. Unfortunately, none that I own. This is probably the best bet though.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://entangle-photo.org/"&gt;Entangle&lt;/a&gt; a front end to Gphoto for Linux.&lt;br /&gt;&lt;/ul&gt;You can sometimes still get a Camera that supports component out - so if you get yourself a frame-grabber, then that might be a good option.  A cheap firewire camera can be purchased from &lt;a href="http://www.theimagingsource.com/en_US/"&gt;The Imaging Source&lt;/a&gt;, so that might be the best option, but is still likely to be out of the range for an amateur VJ or hobby robotics project.&lt;br /&gt;&lt;br /&gt;If anyone has any suggestions for a cheap camcorder/camera that can provide firewire or USB streaming, please let me know!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-287674386249613180?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/287674386249613180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=287674386249613180' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/287674386249613180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/287674386249613180'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/05/consumer-camera-streaming.html' title='Consumer Camera Streaming'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/S_0bc7wFgdI/AAAAAAAAARE/ygwG-8AEIrU/s72-c/PSRemote+Pro1.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-9059772076660312238</id><published>2010-05-21T11:08:00.000+08:00</published><updated>2010-06-04T11:10:06.261+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><title type='text'>Applying forces</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/TAhuO82-LJI/AAAAAAAAARM/OZv10IJh_k4/s1600/Screen+shot+2010-06-04+at+11.07.55+AM.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_nHcDA3NyAms/TAhuO82-LJI/AAAAAAAAARM/OZv10IJh_k4/s320/Screen+shot+2010-06-04+at+11.07.55+AM.png" /&gt;&lt;/a&gt;&lt;/div&gt;In many robotics, graphics, and physics applications some object must be 'moved' by applying a force. Doing this the naive way will often result in very unstable behaviour. There are a number of very simple steps that can be taken to improve the situation. First of all, don't just directly update the position from some overall calculated force (or rather, impulse in this case), instead accumulate a velocity using standard integration. That is:&lt;br /&gt;&lt;pre&gt;velocity += acceleration*dt&lt;br /&gt;position += velocity*dt&lt;br /&gt;&lt;/pre&gt;This is a good first step, and many people stop there and discover that they are still left with large oscillation problems. This is due to the poor first-order integrator (Euler) and the lack of damping. Adding damping and velocity limiting will help:&lt;br /&gt;&lt;pre&gt;velocity += acceleration*dt&lt;br /&gt;velocity = clamp(velocity, min, max)&lt;br /&gt;velocity *= dampen //eg: 0.98&lt;br /&gt;position += velocity*dt&lt;br /&gt;&lt;/pre&gt;Hopefully your system is acting closer to how you expected. At this point if you still have some minor oscillation and odd edge cases you can probably solve them through more advanced techniques. If your still not getting a behaviour close to what you want then try a completely different approach.&lt;br /&gt;&lt;br /&gt;The final quick and easy step to improve performance is to improve the integrator. A simple leap-frog (velocity-verlet) integrator will provide decent performance (no need to go to RK45!):&lt;br /&gt;&lt;pre&gt;velocity += acceleration*dt&lt;br /&gt;velocity = clamp(velocity, min, max)&lt;br /&gt;velocity *= dampen //eg: 0.98&lt;br /&gt;position += velocity*dt + 0.5*acceleration*dt*dt&lt;br /&gt;&lt;/pre&gt;Done!&lt;br /&gt;&lt;br /&gt;Now all your robot path-planning, navigation, graphics particle systems, and cloth-simulations will be up and running. Plenty of research papers to read if you want to keep improving it!&lt;br /&gt;&lt;br /&gt;I'll leave you with this real life video illusion of marbles rolling up a slope:&lt;br /&gt;&lt;object height="385" width="640"&gt;&lt;param name="movie" value="http://www.youtube.com/v/hAXm0dIuyug&amp;hl=en_US&amp;fs=1&amp;"&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/hAXm0dIuyug&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-9059772076660312238?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/9059772076660312238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=9059772076660312238' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/9059772076660312238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/9059772076660312238'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/06/applying-forces.html' title='Applying forces'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/TAhuO82-LJI/AAAAAAAAARM/OZv10IJh_k4/s72-c/Screen+shot+2010-06-04+at+11.07.55+AM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-7644227328185400313</id><published>2010-05-10T23:29:00.046+08:00</published><updated>2010-05-14T00:29:06.210+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><title type='text'>Inverting Matrix - SVD (singular value decomposition)</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/S-wocvMC_aI/AAAAAAAAAQ8/E9VvJ2uT_xU/s1600/minerva.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/S-wocvMC_aI/AAAAAAAAAQ8/E9VvJ2uT_xU/s320/minerva.png" /&gt;&lt;/a&gt;&lt;/div&gt;Every once in a while you find yourself needing to solve a set of equations, or invert a matrix, or worse yet, invert a non-square matrix (eg: pseudo-inverse for manipulator inverse kinematics path control (See: Minerva IK control image on right, work I did at TUM) or kalman filtering). This is when a handy mathematical tool 'singular value decomposition' comes in to play. &lt;br /&gt;&lt;br /&gt;In essence the SVD decomposes a matrix 'M' into three other matrices with special properties, making them easier to manipulate. The SVD equation is:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/S-wd4zipj5I/AAAAAAAAAQs/0duJ9MSgJ_Y/s1600/gif.latex.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/S-wd4zipj5I/AAAAAAAAAQs/0duJ9MSgJ_Y/s320/gif.latex.gif" /&gt;&lt;/a&gt;&lt;/div&gt;Where:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;U is a matrix whose columns are the eigenvectors of the M * M transposed matrix. (AKA left eigenvectors)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;S is a diagonal matrix whose diagonal elements are the singular values of M.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;V is a matrix whose columns are the eigenvectors of the M transposed * M matrix. (AKA right eigenvectors) &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Discussing eigenvalues and eigenvectors I'll leave for another time, but they are quite straight-forward to calculate (get the matrix subtract a constant * I , take the determinant, equate to zero and solve, that gets you the eigenvalues!).&lt;br /&gt;&lt;br /&gt;Now, how do you use the SVD to invert a matrix? Using a few matrix (inversion) identities (See &lt;a href="http://matrixcookbook.com/"&gt;the Matrix Cook Book&lt;/a&gt;, basic identity 1):&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/S-wilY8xH3I/AAAAAAAAAQ0/P4lhnVHccuc/s1600/gif-1.latex.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_nHcDA3NyAms/S-wilY8xH3I/AAAAAAAAAQ0/P4lhnVHccuc/s320/gif-1.latex.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;So now we just need a way to invert a diagonal matrix, which couldn't be easier. To invert a square diagonal matrix you simple invert each element of the matrix.&lt;br /&gt;What if the matrix isn't square?&lt;br /&gt;Well for that, we can just use the pseudo-inverse: we just invert each element of the matrix, and then transpose it. Done!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.miislita.com/information-retrieval-tutorial/svd-lsi-tutorial-1-understanding.html"&gt;&lt;br /&gt;A good tutorial on the SVD can be found here by Dr. E. Garcia&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-7644227328185400313?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/7644227328185400313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=7644227328185400313' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7644227328185400313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7644227328185400313'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/05/inverting-matrix-svd-singular-value.html' title='Inverting Matrix - SVD (singular value decomposition)'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_nHcDA3NyAms/S-wocvMC_aI/AAAAAAAAAQ8/E9VvJ2uT_xU/s72-c/minerva.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-8191174078188125700</id><published>2010-05-01T20:04:00.002+08:00</published><updated>2011-04-01T19:37:57.554+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><title type='text'>Kalman Filters</title><content type='html'>(EDIT: See also &lt;a href="http://adrianboeing.blogspot.com/2010/08/kalman-filters-part-2.html"&gt;Kalman Filter's Part 2&lt;/a&gt;)&lt;br /&gt;I've been looking into a number of sensor fusion techniques, including &lt;a href="http://en.wikipedia.org/wiki/Particle_filter"&gt;Particle Filters&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Kalman_filter"&gt;Kalman Filters&lt;/a&gt; (EKF,UKF, etc). I was looking for something easy to implement, easy to use, and not too computationally intensive.&lt;br /&gt;&lt;br /&gt;I've always been a bit sceptical as to the advantages of a Kalman filter over an &lt;a href="http://adrianboeing.blogspot.com/2010/03/alpha-beta-filters.html"&gt;Alpha-Beta filter&lt;/a&gt;, in terms of performance gained vs cost (i.e.: difficulty to implement &amp;amp; use). For most simple tasks, the Alpha-Beta filter seems to work fine. (Similarly ABG vs AB).&lt;br /&gt;&lt;br /&gt;Particle filters appeared advantageous to me, as they are relatively intuitive and aren't that hard to use, and easy to extend. The difficulty in implementing them can be overcome by using an existing library,&lt;br /&gt;&lt;br /&gt;Kalman filters in my opinion have as a major disadvantage of being difficult to use (you need to construct multiple models), but are relatively easy to implement and computationally efficient. Thus, the use of an existing library doesn't help much.&lt;br /&gt;&lt;br /&gt;I spoke to two experts in the field, &lt;a href="http://www.mrt.uni-karlsruhe.de/ziegler.php"&gt;Julius Ziegler&lt;/a&gt; (who worked on the DARPA Grand Challenge Annieway vehicle with me) and &lt;a href="http://www.rrfx.net/"&gt;Rob Reid&lt;/a&gt; (a local, working on visual SLAM with Kalman filters). Both suggested that Kalman filters would be the most appropriate choice. (Reading various papers seems to indicate a merged (E)Kalman &amp;amp; Particle filter approach is the winner) &lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Kalman_filter"&gt;Wikipedia provides an overview of Kalman filters&lt;/a&gt;, but the real problem is in understanding what all the symbols actually mean, and how it works.&lt;br /&gt;&lt;br /&gt;Like alpha-beta, Kalman filters are prediction-correction filters. That is, they make a prediction, then correct it to provide the final estimate of the systems state. Alpha-Beta's don't have a natural extension to include control inputs, or system identification techniques. They are also (effectively) constrained to linear position/velocity tracking. Kalman filters can be extended to handle non-linear conditions.&lt;br /&gt;&lt;br /&gt;In essence a Kalman filter will (vaguely):&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Estimate the state (from previous)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Determine the error&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Predict the next state&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Predict the next error&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Measure the system&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Update the state calculations&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Update the error calculations&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Bellow are the equations that represent this process, followed by the definitions of each symbol: &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/S9wgQYzoE6I/AAAAAAAAAQk/zR9YElumxlU/s1600/kalmaneq.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_nHcDA3NyAms/S9wgQYzoE6I/AAAAAAAAAQk/zR9YElumxlU/s320/kalmaneq.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;pre&gt;x_temp_est = A * x_est(last) + B * u_control_input&lt;br /&gt;P_temp = A * P(last) * A^T + Q&lt;br /&gt;K = P_temp * H^T * (H* P_temp * H^T + R)^-1&lt;br /&gt;x_est = x_temp_est + K * (z_measured - H * x_temp_est) &lt;br /&gt;P = (I - K*H) * P_temp&lt;br /&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;x - is the state we want to estimate (e.g. position)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;u - is the input to the control system (if it exists) (e.g. a force)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A - state (model) matrix, how to get from last state, to next state (e.g.: position += velocity *dt). (Some people (eg: engineers) use an alternative notation 'F' for this matrix)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;B - is the input matrix (Some people use an alternative notation 'G' for this matrix)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;H - is the measurement matrix (what are we measuring?) e.g.: position or velocity, etc.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Q - is the process noise covariance matrix (you just 'know' this)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;R - is the measurement noise covariance matrix (likewise, you 'know' this, usually from measurements, data sheets, etc, ie: how noisy are your sensors?)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;P - the estimate error covariance matrix (calculated)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;K - the kalman gain (calculated)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The things you must 'know' are: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;How your system moves from one state to the next (e.g. given a current position, velocity, change in time, what will the next state be?) =&amp;gt; This is the 'A' or 'F' matrix&lt;br /&gt;&lt;/li&gt;&lt;li&gt;What are you able to measure? (Maybe just acceleration, or just position?) =&amp;gt; This is the H matrix&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The amount of noise in your measurements and the state-transitions (e.g. the standard deviation of the signal noise, and how 'wrong' your simplified model of the state-transitions are) =&amp;gt; These are Q and R matrices&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Completely confused? Good. Some examples will help clear this whole mess up. First, a simple example where we are observing a noisy-constant. (e.g. measuring the height of a water-tank with a poor quality sensor)  We have no control input so we can ignore the B and u terms. We have no state-transition model (it is a constant!) so we can set A to identity (i.e. one). Our first equation becomes: &lt;br /&gt;&lt;pre&gt;x_temp_est = x_est(last)&lt;/pre&gt;Subsequently the second equation becomes: &lt;br /&gt;&lt;pre&gt;P_temp = P(last) + Q&lt;br /&gt;&lt;/pre&gt;Where Q is our estimation of the variance in our state transition. Since we are measuring a constant, this value should be small. (Remember the real world always has noise, so assuming zero noise is always a bad idea)  We measure the state directly (i.e. the noisy value of the constant) so the H matrix is also identity.  This means: &lt;br /&gt;&lt;pre&gt;K = P_temp * (P_temp + R)^-1&lt;br /&gt;x_est = x_temp_est + K * (z_measured - x_temp_est) &lt;br /&gt;P = (1- K) * P_temp&lt;br /&gt;&lt;/pre&gt;Again, we keep R since that is our all-important measurement noise estimate.  Now let's see this in action in C: &lt;br /&gt;&lt;pre&gt;&lt;span style="color: green;"&gt;/** A simple kalman filter example by Adrian Boeing  &lt;br /&gt; www.adrianboeing.com  &lt;br /&gt; */&lt;/span&gt;  &lt;br /&gt;&lt;br /&gt;#&lt;span style="color: blue;"&gt;include&lt;/span&gt; &amp;lt;stdio.h&amp;gt; &lt;br /&gt;#&lt;span style="color: blue;"&gt;include&lt;/span&gt; &amp;lt;stdlib.h&amp;gt; &lt;br /&gt;#&lt;span style="color: blue;"&gt;include&lt;/span&gt; &amp;lt;math.h&amp;gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;double&lt;/span&gt; frand() { &lt;br /&gt;    &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: maroon;"&gt;2&lt;/span&gt;*((rand()/(&lt;span style="color: blue;"&gt;double&lt;/span&gt;)RAND_MAX) - &lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.5&lt;/span&gt;); &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;int&lt;/span&gt; main() { &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: green;"&gt;//initial values for the kalman filter&lt;/span&gt; &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; x_est_last = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;;&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; P_last = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;; &lt;br /&gt;    &lt;span style="color: green;"&gt;//the noise in the system&lt;/span&gt; &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; Q = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.022&lt;/span&gt;;&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; R = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.617&lt;/span&gt;;&lt;br /&gt;     &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; K; &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; P; &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; P_temp; &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; x_temp_est; &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; x_est; &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; z_measured; &lt;span style="color: green;"&gt;//the 'noisy' value we measured&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; z_real = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.5&lt;/span&gt;; &lt;span style="color: green;"&gt;//the ideal value we wish to measure&lt;/span&gt;&lt;br /&gt;     &lt;br /&gt;    srand(&lt;span style="color: maroon;"&gt;0&lt;/span&gt;); &lt;br /&gt;     &lt;br /&gt;    &lt;span style="color: green;"&gt;//initialize with a measurement&lt;/span&gt; &lt;br /&gt;    x_est_last = z_real + frand()*&lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.09&lt;/span&gt;;&lt;br /&gt;     &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; sum_error_kalman = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;;&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; sum_error_measure = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;;&lt;br /&gt;     &lt;br /&gt;    &lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;int&lt;/span&gt; i=&lt;span style="color: maroon;"&gt;0&lt;/span&gt;;i&amp;lt;&lt;span style="color: maroon;"&gt;30&lt;/span&gt;;i++) {&lt;br /&gt;        &lt;span style="color: green;"&gt;//do a prediction&lt;/span&gt; &lt;br /&gt;        x_temp_est = x_est_last; &lt;br /&gt;        P_temp = P_last + Q; &lt;br /&gt;        &lt;span style="color: green;"&gt;//calculate the Kalman gain&lt;/span&gt; &lt;br /&gt;        K = P_temp * (&lt;span style="color: maroon;"&gt;1&lt;/span&gt;&lt;span style="color: maroon;"&gt;.0&lt;/span&gt;/(P_temp + R));&lt;br /&gt;        &lt;span style="color: green;"&gt;//measure&lt;/span&gt; &lt;br /&gt;        z_measured = z_real + frand()*&lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.09&lt;/span&gt;; &lt;span style="color: green;"&gt;//the real measurement plus noise&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: green;"&gt;//correct&lt;/span&gt; &lt;br /&gt;        x_est = x_temp_est + K * (z_measured - x_temp_est);  &lt;br /&gt;        P = (&lt;span style="color: maroon;"&gt;1&lt;/span&gt;- K) * P_temp; &lt;br /&gt;        &lt;span style="color: green;"&gt;//we have our new system&lt;/span&gt; &lt;br /&gt;         &lt;br /&gt;        printf(&lt;span style="color: maroon;"&gt;"Ideal    position: %6.3f \n"&lt;/span&gt;,z_real); &lt;br /&gt;        printf(&lt;span style="color: maroon;"&gt;"Mesaured position: %6.3f [diff:%.3f]\n"&lt;/span&gt;,z_measured,fabs(z_real-z_measured)); &lt;br /&gt;        printf(&lt;span style="color: maroon;"&gt;"Kalman   position: %6.3f [diff:%.3f]\n"&lt;/span&gt;,x_est,fabs(z_real - x_est)); &lt;br /&gt;         &lt;br /&gt;        sum_error_kalman += fabs(z_real - x_est); &lt;br /&gt;        sum_error_measure += fabs(z_real-z_measured); &lt;br /&gt;         &lt;br /&gt;        &lt;span style="color: green;"&gt;//update our last's&lt;/span&gt; &lt;br /&gt;        P_last = P; &lt;br /&gt;        x_est_last = x_est; &lt;br /&gt;    } &lt;br /&gt;     &lt;br /&gt;    printf(&lt;span style="color: maroon;"&gt;"Total error if using raw measured:  %f\n"&lt;/span&gt;,sum_error_measure);&lt;br /&gt;    printf(&lt;span style="color: maroon;"&gt;"Total error if using kalman filter: %f\n"&lt;/span&gt;,sum_error_kalman);&lt;br /&gt;    printf(&lt;span style="color: maroon;"&gt;"Reduction in error: %d%% \n"&lt;/span&gt;,&lt;span style="color: maroon;"&gt;100&lt;/span&gt;-(&lt;span style="color: blue;"&gt;int&lt;/span&gt;)((sum_error_kalman/sum_error_measure)*&lt;span style="color: maroon;"&gt;100&lt;/span&gt;));&lt;br /&gt;     &lt;br /&gt;     &lt;br /&gt;    &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: maroon;"&gt;0&lt;/span&gt;; &lt;br /&gt;}&lt;/pre&gt;This should generate output similar to: &lt;br /&gt;&lt;pre&gt;Mesaured position:  0.562 [diff:0.062]&lt;br /&gt;Kalman   position:  0.498 [diff:0.002]&lt;br /&gt;Ideal    position:  0.500 &lt;br /&gt;Mesaured position:  0.563 [diff:0.063]&lt;br /&gt;Kalman   position:  0.509 [diff:0.009]&lt;br /&gt;Total error if using raw measured:  1.566003&lt;br /&gt;Total error if using kalman filter: 0.441561&lt;br /&gt;Reduction in error: 72% &lt;br /&gt;&lt;/pre&gt;More (non-trivial) examples will follow soon.  In the meantime I can suggest the following resources: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;http://www.cs.unc.edu/~tracker/ref/s2001/kalman/index.html&lt;br /&gt;&lt;/li&gt;&lt;li&gt;http://www.cs.cmu.edu/~biorobotics/papers/sbp_papers/integrated3/kleeman_kalman_basics.pdf&lt;br /&gt;&lt;/li&gt;&lt;li&gt;http://www.acfr.usyd.edu.au/education/multiSensorDataFusion.shtml&lt;br /&gt;&lt;/li&gt;&lt;li&gt;http://www.ee.pdx.edu/~greenwd/kalman_overview.pdf&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Source code/libraries: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;http://kalman.sourceforge.net/&lt;br /&gt;&lt;/li&gt;&lt;li&gt;http://bayesclasses.sourceforge.net/&lt;br /&gt;&lt;/li&gt;&lt;li&gt;http://www.memsense.com/index.php/Product-Pages/kalman-filter-library.html&lt;br /&gt;&lt;/li&gt;&lt;li&gt;http://sites.google.com/site/jordiuavs/Home/kalman_filter_by_Jordi.txt&lt;br /&gt;&lt;/li&gt;&lt;li&gt;http://www.orocos.org/bfl&lt;br /&gt;&lt;/li&gt;&lt;li&gt;http://www.scipy.org/Cookbook/KalmanFiltering&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/17188375-8191174078188125700?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/8191174078188125700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=8191174078188125700' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8191174078188125700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/8191174078188125700'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/05/kalman-filters.html' title='Kalman Filters'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/S9wgQYzoE6I/AAAAAAAAAQk/zR9YElumxlU/s72-c/kalmaneq.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-3592464382734289467</id><published>2010-04-30T12:06:00.000+08:00</published><updated>2010-04-30T12:06:41.950+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='magic2010'/><title type='text'>Robots and Robot Competitions</title><content type='html'>I am part of an &lt;a href="http://wambot.org/"&gt;Australian team that has entered the MAGIC 2010 competition, Team WAMbot&lt;/a&gt;. MAGIC 2010 is an exciting challenge for coordinating multiple autonomous vehicles for mapping, surveillance and tracking tasks. This is sure to prove to be an exciting challenge that will push robots forward in terms of capabilities and reliability. Although many robots can already do similar tasks, I have not seen any demonstration of the interaction of all of these capabilities, reliably for an extended period of time.&lt;br /&gt;&lt;br /&gt;A previous challenge that sparked great interest that was also funded by the military were the &lt;a href="http://en.wikipedia.org/wiki/DARPA_Grand_Challenge"&gt;DARPA Grand Challenge&lt;/a&gt;'s. However I believe one group has taken onboard an even more monumental challenge, &lt;a href="http://vislab.it/Projects/view/32/VisLab"&gt;the VisLab's Intercontinental challenge to cross from Rome, Italy to Shanghai, China&lt;/a&gt;. VisLab have a unique pure-vision approach (although I doubt they will stick to this for this particular challenge), have been a leader in the autonomous automotive field for years and have done some very impressive work. They are brave enough to walk infront of their vehicles and trust them to swerve out of the way to avoid them. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/S9o7ZNY8doI/AAAAAAAAAQc/uyKVMU2m6IU/s1600/vislab-logo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_nHcDA3NyAms/S9o7ZNY8doI/AAAAAAAAAQc/uyKVMU2m6IU/s320/vislab-logo.png" /&gt;&lt;/a&gt;&lt;/div&gt;I believe the VisLab challenge will be a very tough test, unlike previous ground-breaking driving trips, like &lt;a href="http://www.unibw.de/lrt8/forschung-en"&gt;UniBW&lt;/a&gt;'s &lt;a href="http://en.wikipedia.org/wiki/VaMP"&gt;1000 mile autonomous journey&lt;/a&gt; in the 1990's that followed clean Autobahn lane markings, the VisLab's challenge will travel on unreliable roads for a much longer time and need to deal with pedestrians, animals, etc, etc. They do get the slight bonus of being able to use GPS navigation.&lt;br /&gt;&lt;br /&gt;The VisLab guys are very friendly and helpful people, so I wish them the best of luck in this challenging and ground-breaking endeavour!&lt;br /&gt;&lt;br /&gt;I'll leave you with some interesting Robotics videos:&lt;br /&gt;This blimp seems similar to the Festo blimp, but it is powered by electroactive polymers.&lt;br /&gt;&lt;object height="385" width="640"&gt;&lt;param name="movie" value="http://www.youtube.com/v/6cdfWdHZRrE&amp;color1=0xb1b1b1&amp;color2=0xd0d0d0&amp;hl=en_US&amp;feature=player_embedded&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/6cdfWdHZRrE&amp;color1=0xb1b1b1&amp;color2=0xd0d0d0&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;And a robot balancing on a ball, not unlike the &lt;a href="http://robotics.ee.uwa.edu.au/eyebot/doc/robots/ballybot.html"&gt;BallyBot&lt;/a&gt; from our lab.&lt;br /&gt;&lt;object height="385" width="640"&gt;&lt;param name="movie" value="http://www.youtube.com/v/bI06lujiD7E&amp;color1=0xb1b1b1&amp;color2=0xd0d0d0&amp;hl=en_US&amp;feature=player_embedded&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/bI06lujiD7E&amp;color1=0xb1b1b1&amp;color2=0xd0d0d0&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;And VAIL's autonomous parking has made some impact on the web, no idea why, it doesn't seem much more advanced than the autonomous parking we've been seeing for years since the DARPA Urban Challenge. Still, it is neat:&lt;br /&gt;&lt;object height="385" width="480"&gt;&lt;param name="movie" value="http://www.youtube.com/v/YVuG7HAt-r4&amp;hl=en_US&amp;fs=1&amp;rel=0"&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/YVuG7HAt-r4&amp;hl=en_US&amp;fs=1&amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-3592464382734289467?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/3592464382734289467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=3592464382734289467' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3592464382734289467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3592464382734289467'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/04/robots-and-robot-competitions.html' title='Robots and Robot Competitions'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nHcDA3NyAms/S9o7ZNY8doI/AAAAAAAAAQc/uyKVMU2m6IU/s72-c/vislab-logo.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-7411128345126286357</id><published>2010-04-29T23:18:00.000+08:00</published><updated>2010-04-29T23:18:41.112+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='compilers'/><title type='text'>Build Systems</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/S9mjNlg-aKI/AAAAAAAAAQU/mMTwrwCKHOE/s1600/premake_logo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_nHcDA3NyAms/S9mjNlg-aKI/AAAAAAAAAQU/mMTwrwCKHOE/s320/premake_logo.png" /&gt;&lt;/a&gt;&lt;/div&gt;Managing and building software packages is a big task. There are a few options on what build system you can use. Windows users prefer Visual Studio 'solutions' and 'projects', *nix users prefer Makefiles. Ideally, cross-platform tools are what everyone wants.&lt;br /&gt;&lt;br /&gt;Some popular choices include:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.cmake.org/"&gt;CMake&lt;/a&gt; - a 'cross-platform' make, popular with a lot of projects. (We use it in &lt;a href="http://pal.sf.net/"&gt;PAL&lt;/a&gt; thanks to &lt;a href="http://sukender.free.fr/"&gt;Benoit Neil&lt;/a&gt;'s contributions). My gripe with CMake is its complexity. The fact that there is a complete &lt;a href="http://www.kitware.com/products/cmakebook.html"&gt;book&lt;/a&gt; to describe it is a scary thought.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://premake.sourceforge.net/"&gt;Premake&lt;/a&gt; - is a less popular choice (a few large projects use it, eg: ODE, PAL previously used it). It uses Lua-script, and it is my personal favourite due to its simplicity whilst still being very powerful. Premake is a bit windows-orientated, which helped me as I came from a Windows development background.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;bjam, the boost build system. I've not used this one too much, but it is apparently decent.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.scons.org/"&gt;scons&lt;/a&gt;, a python-based build system. I've not used it much, but it seems quite complex. (&lt;a href="http://robotics.usc.edu/~drumwrig/index.html"&gt;Evan Drumwright&lt;/a&gt; developed an scons build system for a PAL benchmark tool)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Premake (4) is quite easy to use, below is a very simple template for its use: &lt;br /&gt;&lt;pre&gt;solution "NAME"&lt;br /&gt; configurations {"Debug", "Release"}&lt;br /&gt; targetdir "bin"&lt;br /&gt; language "C++"&lt;br /&gt; location "build"&lt;br /&gt; includedirs {"src", "."}&lt;br /&gt;&lt;br /&gt;project "NAME"&lt;br /&gt; kind "ConsoleApp"&lt;br /&gt; files {"src/*.cpp"}&lt;br /&gt; links {"lib"}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Simply invoke with "premake vs2008" for windows, or "premake gmake" under *nix.&lt;br /&gt;The lua script lets you easily extend the script to copy DLL's, set up custom include paths for each user, etc, etc.&lt;br /&gt;&lt;br /&gt;This should help you get started with cross-platform build solutions!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-7411128345126286357?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/7411128345126286357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=7411128345126286357' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7411128345126286357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7411128345126286357'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/04/build-systems.html' title='Build Systems'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/S9mjNlg-aKI/AAAAAAAAAQU/mMTwrwCKHOE/s72-c/premake_logo.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-7067677811621869143</id><published>2010-04-16T23:58:00.000+08:00</published><updated>2010-04-16T23:58:48.421+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><title type='text'>Online Project Management Software</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_nHcDA3NyAms/S8iI0qnYvKI/AAAAAAAAAQM/B4w1QbIextM/s1600/247.png_thumbnail128x160.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_nHcDA3NyAms/S8iI0qnYvKI/AAAAAAAAAQM/B4w1QbIextM/s320/247.png_thumbnail128x160.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;Every project requires some form of tracking, whether it is a simple to-do list or a highly detailed gantt chart. At some stage a some formal planning must take place, and if you are collaborating across different physical locations an online tool can really help.&lt;br /&gt;&lt;br /&gt;I had a few requirements:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Ability to track milestones &amp;amp; tasks&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Sepecifiy interdependencies between tasks&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Track issues/bugs (Ticketing)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A visual display of the schedule (eg: Gantt, Time/Time, or Burndown chart)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;I also wanted the tool to allow different management approaches (ie: not a purely scrum-based tool), and the usual niceties such as email notifications and a blog/wiki/forum/etc.  Finally I wanted all this for free (ofcourse!).  The usual suggestions are Bugzilla, Trac and MediaWiki, however none of these provide all the features we needed.  Some of the better products I found included: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.redmine.org/"&gt;Redmine&lt;/a&gt; - A free (open source) web application with issue tracking, gantt charts, email notifications, wiki, forums, time tracking, etc. Unfortunately it is still quite 'beta' but definately one to watch for the future.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.assembla.com/"&gt;Assembla&lt;/a&gt; - A paid web service with task management, issue tracking, some scrum support, wikis, forums, but no visual way of representing a schedule as far as I could tell.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.clockingit.com/"&gt;Clocking IT&lt;/a&gt; - A free (closed) web service that provides project tracking, it looks great but seemed a bit too simplistic for my needs. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.codespaces.com/"&gt;CodeSpaces&lt;/a&gt; - A paid service, but offers free accounts. Easy to use, supports visual scheduling, forums, but is tightly SVN and scrum based (card walls, stories, etc.) and the help was a bit poor. I seriously investigated this option but decided against it in the end, however I can recommend this option.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.comindwork.com/"&gt;CoMindWork&lt;/a&gt; - A paid service, but offers a limited free version. Can be both online and installed, provides a decent visual gantt chart with task and time tracking, issue tracking, email notifications, wiki, blog, and good help videos and instructions all through making it easy to learn. A big bonus is that it directly imports and exports between Microsoft Project, integrates with BaseCamp and provides an API for import/export. It also has a bit of a &lt;a href="http://plone.org/"&gt;plone&lt;/a&gt;-like feel, which I was comfortable with having used it before.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;So CoMindWork was the winner for me.   Some of the other promising ones I was looking at included: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Zoho projects&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Unfuddle&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Agile42&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;but since I'd found CoMindWork by then I didn't look into them into too much depth.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-7067677811621869143?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/7067677811621869143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=7067677811621869143' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7067677811621869143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/7067677811621869143'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/04/online-project-management-software.html' title='Online Project Management Software'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nHcDA3NyAms/S8iI0qnYvKI/AAAAAAAAAQM/B4w1QbIextM/s72-c/247.png_thumbnail128x160.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-20179145898582073</id><published>2010-04-10T22:39:00.000+08:00</published><updated>2010-04-10T22:39:03.087+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>wxWidgets on OSX</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/S8CNcU6UnuI/AAAAAAAAAQE/YdTZXtpEt38/s1600/Screen+shot+2010-04-10+at+10.30.24+PM.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_nHcDA3NyAms/S8CNcU6UnuI/AAAAAAAAAQE/YdTZXtpEt38/s320/Screen+shot+2010-04-10+at+10.30.24+PM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://www.wxwindows.org/"&gt;wxWidgets&lt;/a&gt; is one of the worst toolkits known to man. Unfortunately, people keep using it, so I need to keep compiling it. I personally prefer &lt;a href="http://www.fltk.org/"&gt;FLTK&lt;/a&gt;, my only complaint about FLTK is that it can look pretty poor. Recently I have been looking around for a very light-weight native cross platform widget toolkit - no luck so far. (Suggestions anyone?)&lt;br /&gt;&lt;br /&gt;Here are some instructions on compling wxWidgets (ex wxWindows) for Apple Mac OSX Snow Leopard. To begin, download wxMac, decompress it, open a terminal and navigate to the base wxMac directory.&lt;br /&gt;&lt;pre&gt;mkdir osx_build&lt;br /&gt;cd osx_build&lt;br /&gt;&lt;/pre&gt;You will most probably want to have OpenGL support with wxWidgets, so remember the "--with-opengl" flag. As with most projects, the 64bit support on OSX is flaky, so it is best to compile for 32bit using "-arch i386". Hopefully this won't be necessary in the near future.&lt;br /&gt;&lt;pre&gt;../configure --with-opengl CFLAGS="-arch i386" CXXFLAGS="-arch i386" CPPFLAGS="-arch i386" LDFLAGS="-arch i386" OBJCFLAGS="-arch i386" OBJCXXFLAGS="-arch i386" &lt;br /&gt;&lt;/pre&gt;(Note: other handy options are: --with-cocoa, --disable-shared --enable-static, --enable-unicode, --enable-debug. At present Cocoa support is dubious, again, this may change in future.)&lt;br /&gt;&lt;br /&gt;(you may wish to confirm that opengl canvas is enabled - see: &lt;br /&gt;/usr/lib/wx/include/mac-unicode-debug-2.8/wx/setup.h)&lt;br /&gt;&lt;pre&gt;make&lt;br /&gt;&lt;/pre&gt;You should have a lib directory with all the dylib's in it.&lt;br /&gt;Unfortunately, for wx to work, you will need to install it.&lt;br /&gt;&lt;pre&gt;sudo make install&lt;br /&gt;&lt;br /&gt;make samples&lt;br /&gt;&lt;/pre&gt;This should generate a whole bunch of samples in the osx_build/samples directory&lt;br /&gt;&lt;br /&gt;Now you can run the samples! (Note: the samples can not be run from the command line, you need to run the applications, otherwise the program will not gain focus and you won't be able to click on any of the buttons!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-20179145898582073?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/20179145898582073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=20179145898582073' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/20179145898582073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/20179145898582073'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/04/wxwidgets-on-osx.html' title='wxWidgets on OSX'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/S8CNcU6UnuI/AAAAAAAAAQE/YdTZXtpEt38/s72-c/Screen+shot+2010-04-10+at+10.30.24+PM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-5900775393176863349</id><published>2010-04-10T22:34:00.000+08:00</published><updated>2010-04-10T22:34:46.408+08:00</updated><title type='text'>Catchup: Life</title><content type='html'>I've had a very busy time, I was in the UK doing commissioning work, returned to Perth for a meeting with Thales managers about MAGIC 2010, moved house, easter, and got sick for a week.&lt;br /&gt;&lt;br /&gt;This totally destroyed my plans for posting a whole set of catchup posts so I guess that will have to wait.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-5900775393176863349?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/5900775393176863349/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=5900775393176863349' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5900775393176863349'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/5900775393176863349'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/04/catchup-life.html' title='Catchup: Life'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-6596500631808380432</id><published>2010-03-09T21:15:00.001+08:00</published><updated>2010-03-09T21:16:40.035+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><category scheme='http://www.blogger.com/atom/ns#' term='PAL'/><title type='text'>Pixelux Digital Molecular Matter engine - Free license soon!</title><content type='html'>&lt;a href="http://www.amd.com/us/press-releases/Pages/amd-ecosystem-2010mar8.aspx"&gt;AMD have just announced there will be a free version of the DMM engine&lt;/a&gt;. It sounds like it will be closely integrated with Bullet Physics and provide OpenCL support.&lt;br /&gt;&lt;br /&gt;I'm looking forward to this as DMM is the only realtime finite-element (FEM) based physics engine around. I'm interested to see how well it works.&lt;br /&gt;&lt;br /&gt;Hopefully I can get a copy soon and some time to integrate it into the &lt;a href="http://pal.sf.net/"&gt;Physics Abstraction Layer&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here is a video of DMM to refresh your memory:&lt;br /&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/VFtRbM6i0qY&amp;hl=en_US&amp;fs=1&amp;"&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/VFtRbM6i0qY&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-6596500631808380432?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/6596500631808380432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=6596500631808380432' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6596500631808380432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6596500631808380432'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/03/pixelux-digital-molecular-matter-engine.html' title='Pixelux Digital Molecular Matter engine - Free license soon!'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-454609711424240077</id><published>2010-03-02T09:19:00.001+08:00</published><updated>2011-04-01T19:40:00.792+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Alpha Beta Filters</title><content type='html'>(EDIT: See also &lt;a href="http://adrianboeing.blogspot.com/2010/05/kalman-filters.html"&gt;Kalman filters&lt;/a&gt;)&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/S4xngTiH7OI/AAAAAAAAAP4/ArioPojbbq8/s1600-h/abfilter.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/S4xngTiH7OI/AAAAAAAAAP4/ArioPojbbq8/s320/abfilter.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Alpha_beta_filter"&gt;Alpha-Beta filters&lt;/a&gt; are fairly well explained on wikipedia, and are generally a very easy first-stop solution before heading to Kalman or particle-filter alternatives. (The next obvious step is to extend this to include acceleration (Alpha-Beta-Gamma), and to limit the error/estimates to a sensible range for your application). &lt;br /&gt;&lt;br /&gt;Here is a small example program showing how they work, it generates output similar to this:&lt;br /&gt;&lt;pre&gt;Ideal     position: -0.897 -0.443&lt;br /&gt;Mesaured  position: -0.890 -0.421 [diff:0.029]&lt;br /&gt;AlphaBeta position: -0.898 -0.442 [diff:0.001]&lt;br /&gt;Total error if using raw measured: 1.522438&lt;br /&gt;Total error if using a-b filter:   1.059981&lt;br /&gt;Reduction in error: 69% &lt;br /&gt;&lt;/pre&gt;C source code follows:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: green;"&gt;/** A simple alpha-beta filter example by Adrian Boeing &lt;br /&gt;    www.adrianboeing.com &lt;br /&gt; */&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;#&lt;span style="color: blue;"&gt;include&lt;/span&gt; &amp;lt;stdio.h&amp;gt; &lt;br /&gt;#&lt;span style="color: blue;"&gt;include&lt;/span&gt; &amp;lt;stdlib.h&amp;gt; &lt;br /&gt;#&lt;span style="color: blue;"&gt;include&lt;/span&gt; &amp;lt;math.h&amp;gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;typedef&lt;/span&gt; &lt;span style="color: blue;"&gt;struct&lt;/span&gt; { &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; alpha; &lt;span style="color: green;"&gt;//alpha value (effects x, eg pos)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; beta; &lt;span style="color: green;"&gt;//beta value (effects v, eg vel)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; xk_1; &lt;span style="color: green;"&gt;//current x-estimate&lt;/span&gt; &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; vk_1; &lt;span style="color: green;"&gt;//current v-estimate&lt;/span&gt; &lt;br /&gt;} AlphaBeta; &lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;void&lt;/span&gt; InitializeAlphaBeta(&lt;span style="color: blue;"&gt;float&lt;/span&gt; x_measured, &lt;span style="color: blue;"&gt;float&lt;/span&gt; alpha, &lt;span style="color: blue;"&gt;float&lt;/span&gt; beta, AlphaBeta* pab) {&lt;br /&gt;    pab-&amp;gt;xk_1 = x_measured; &lt;br /&gt;    pab-&amp;gt;vk_1 = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;; &lt;br /&gt;    pab-&amp;gt;alpha = alpha; &lt;br /&gt;    pab-&amp;gt;beta = beta; &lt;br /&gt;}    &lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;void&lt;/span&gt; AlphaBetaFilter(&lt;span style="color: blue;"&gt;float&lt;/span&gt; x_measured, &lt;span style="color: blue;"&gt;float&lt;/span&gt; dt, AlphaBeta* pab) {&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; xk_1 = pab-&amp;gt;xk_1; &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; vk_1 = pab-&amp;gt;vk_1; &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; alpha = pab-&amp;gt;alpha; &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; beta = pab-&amp;gt;beta; &lt;br /&gt;    &lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; xk; &lt;span style="color: green;"&gt;//current system state (ie: position)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; vk; &lt;span style="color: green;"&gt;//derivative of system state (ie: velocity)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;float&lt;/span&gt; rk; &lt;span style="color: green;"&gt;//residual error &lt;/span&gt;&lt;br /&gt;     &lt;br /&gt;    &lt;span style="color: green;"&gt;//update our (estimated) state 'x' from the system (ie pos = pos + vel (last).dt)&lt;/span&gt;&lt;br /&gt;    xk = xk_1 + dt * vk_1; &lt;br /&gt;    &lt;span style="color: green;"&gt;//update (estimated) velocity &lt;/span&gt; &lt;br /&gt;    vk = vk_1; &lt;br /&gt;    &lt;span style="color: green;"&gt;//what is our residual error (mesured - estimated)&lt;/span&gt; &lt;br /&gt;    rk = x_measured - xk;  &lt;br /&gt;    &lt;span style="color: green;"&gt;//update our estimates given the residual error.&lt;/span&gt; &lt;br /&gt;    xk = xk + alpha * rk; &lt;br /&gt;    vk = vk + beta/dt * rk; &lt;br /&gt;    &lt;span style="color: green;"&gt;//finished!&lt;/span&gt; &lt;br /&gt;     &lt;br /&gt;    &lt;span style="color: green;"&gt;//now all our "currents" become our "olds" for next time&lt;/span&gt; &lt;br /&gt;    pab-&amp;gt;vk_1 = vk; &lt;br /&gt;    pab-&amp;gt;xk_1 = xk; &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;double&lt;/span&gt; frand() { &lt;br /&gt;    &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: maroon;"&gt;2&lt;/span&gt;*((rand()/(&lt;span style="color: blue;"&gt;double&lt;/span&gt;)RAND_MAX) - &lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.5&lt;/span&gt;); &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;int&lt;/span&gt; main(&lt;span style="color: blue;"&gt;int&lt;/span&gt; argc, &lt;span style="color: blue;"&gt;char&lt;/span&gt; *argv[]) {&lt;br /&gt;    AlphaBeta ab_x; &lt;br /&gt;    AlphaBeta ab_y; &lt;br /&gt;    &lt;span style="color: blue;"&gt;double&lt;/span&gt; t; &lt;span style="color: green;"&gt;//time&lt;/span&gt; &lt;br /&gt;    &lt;span style="color: blue;"&gt;double&lt;/span&gt; x,y; &lt;span style="color: green;"&gt;//ideal x-y coordinates&lt;/span&gt; &lt;br /&gt;    &lt;span style="color: blue;"&gt;double&lt;/span&gt; xm,ym; &lt;span style="color: green;"&gt;//measured x-y coordinates&lt;/span&gt; &lt;br /&gt;    &lt;span style="color: blue;"&gt;double&lt;/span&gt; xnoise = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;; &lt;span style="color: green;"&gt;//noise we are inserting into our system&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;double&lt;/span&gt; ynoise = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;; &lt;br /&gt;    &lt;span style="color: blue;"&gt;double&lt;/span&gt; m_error = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;; &lt;span style="color: green;"&gt;//total error (measured vs ideal)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;double&lt;/span&gt; ab_error = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;; &lt;span style="color: green;"&gt;//total error (ab filter vs ideal)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;#define&lt;/span&gt; DT &lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.1&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: green;"&gt;//intialize the AB filters&lt;/span&gt; &lt;br /&gt;    InitializeAlphaBeta(&lt;span style="color: maroon;"&gt;1&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.85&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.001&lt;/span&gt;,&amp;amp;ab_x); &lt;span style="color: green;"&gt;//x position&lt;/span&gt;&lt;br /&gt;    InitializeAlphaBeta(&lt;span style="color: maroon;"&gt;0&lt;/span&gt;,&lt;span style="color: maroon;"&gt;1&lt;/span&gt;&lt;span style="color: maroon;"&gt;.27&lt;/span&gt;,&lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.009&lt;/span&gt;,&amp;amp;ab_y); &lt;span style="color: green;"&gt;//y position&lt;/span&gt;&lt;br /&gt;    srand(&lt;span style="color: maroon;"&gt;0&lt;/span&gt;); &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;for&lt;/span&gt; (t = &lt;span style="color: maroon;"&gt;0&lt;/span&gt;; t &amp;lt; &lt;span style="color: maroon;"&gt;4&lt;/span&gt;; t+=DT) {&lt;br /&gt;        &lt;span style="color: green;"&gt;//our 'true' position (A circle)&lt;/span&gt; &lt;br /&gt;        x = cos(t); &lt;br /&gt;        y = sin(t); &lt;br /&gt;        &lt;span style="color: green;"&gt;//update our simulated noise &amp;amp; drift&lt;/span&gt; &lt;br /&gt;        xnoise += frand()*&lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.01&lt;/span&gt;;&lt;br /&gt;        ynoise += frand()*&lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.01&lt;/span&gt;;&lt;br /&gt;        &lt;span style="color: green;"&gt;//our 'measured' position (has some noise)&lt;/span&gt; &lt;br /&gt;        xm = x + xnoise; &lt;br /&gt;        ym = y + ynoise; &lt;br /&gt;        &lt;span style="color: green;"&gt;//our 'filtered' position (removes some noise)&lt;/span&gt; &lt;br /&gt;        AlphaBetaFilter(xm,DT, &amp;amp;ab_x); &lt;br /&gt;        AlphaBetaFilter(ym,DT, &amp;amp;ab_y); &lt;br /&gt;         &lt;br /&gt;        &lt;span style="color: green;"&gt;//print &lt;/span&gt; &lt;br /&gt;        printf(&lt;span style="color: maroon;"&gt;"Ideal     position: %6.3f %6.3f\n"&lt;/span&gt;,x,y); &lt;br /&gt;        printf(&lt;span style="color: maroon;"&gt;"Mesaured  position: %6.3f %6.3f [diff:%.3f]\n"&lt;/span&gt;,xm,ym,fabs(x-xm) + fabs(y-ym)); &lt;br /&gt;        printf(&lt;span style="color: maroon;"&gt;"AlphaBeta position: %6.3f %6.3f [diff:%.3f]\n"&lt;/span&gt;,ab_x.xk_1,ab_y.xk_1,fabs(x-ab_x.xk_1) + fabs(y-ab_y.xk_1)); &lt;br /&gt;         &lt;br /&gt;        &lt;span style="color: green;"&gt;//update error sum (for statistics only)&lt;/span&gt; &lt;br /&gt;        m_error += fabs(x-xm) + fabs(y-ym); &lt;br /&gt;        ab_error += fabs(x-ab_x.xk_1) + fabs(y-ab_y.xk_1); &lt;br /&gt;    } &lt;br /&gt;    printf(&lt;span style="color: maroon;"&gt;"Total error if using raw measured: %f\n"&lt;/span&gt;,m_error);&lt;br /&gt;    printf(&lt;span style="color: maroon;"&gt;"Total error if using a-b filter:   %f\n"&lt;/span&gt;,ab_error); &lt;br /&gt;    printf(&lt;span style="color: maroon;"&gt;"Reduction in error: %d%% \n"&lt;/span&gt;,(&lt;span style="color: blue;"&gt;int&lt;/span&gt;)((ab_error/m_error)*&lt;span style="color: maroon;"&gt;100&lt;/span&gt;));&lt;br /&gt;    &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: maroon;"&gt;0&lt;/span&gt;; &lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-454609711424240077?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/454609711424240077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=454609711424240077' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/454609711424240077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/454609711424240077'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/03/alpha-beta-filters.html' title='Alpha Beta Filters'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_nHcDA3NyAms/S4xngTiH7OI/AAAAAAAAAP4/ArioPojbbq8/s72-c/abfilter.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-3335661367948964486</id><published>2010-03-01T22:34:00.000+08:00</published><updated>2010-03-01T22:34:11.786+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='GPGPU'/><title type='text'>Catchup: Graphics Links Post</title><content type='html'>Again, a set of interesting links from the last few weeks:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.sfml-dev.org/"&gt;Simple and Fast Multimedia Library&lt;/a&gt;, a SDL replacement with a few more modern concepts. (eg: shaders!)&lt;br /&gt;&lt;li&gt;The OpenCL debugger, &lt;a href="http://gpgpu.org/2010/02/10/gdebugger-for-opencl-beta-program"&gt;gDEBugger CL is in public beta&lt;/a&gt; for Windows, Mac OS X and Linux.&lt;br /&gt;&lt;li&gt;&lt;a href="http://developer.amd.com/gpu/ATIStreamSDK/Pages/default.aspx"&gt;ATI Stream Software Development Kit (SDK) v2.01&lt;/a&gt; now supports DirectX / OpenCL interoperability, plus debugging with GDB! A giant leap forward for OpenCL by AMD!&lt;br /&gt;&lt;li&gt;Sander Van Rossen has put together a set of interesting posts on &lt;a href="http://sandervanrossen.blogspot.com/2009/12/realtime-csg-part-1.html"&gt;implementing a constructive solid geometry (CSG) system&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;&lt;a href="http://caustic.com/dev_emulation_register.php"&gt;OpenRL&lt;/a&gt; (raytracing language) has gone beta. I've not had positive experiences with Caustic so far. Wait and see I guess.&lt;br /&gt;&lt;li&gt;Apparently, someone managed a &lt;a href="http://www.nvidia.com/object/cuda_apps_flash_new.html#state=detailsOpen;aid=aa417b5b-e0cc-446a-9fca-a93e14d4868b"&gt;20x speedup for SQL select queries with the GPU&lt;/a&gt;. I guess I need to eat my words. I'm still not convinced that this is really a CPU-intensive issue. (Maybe for scheduling and retrieving flight prices - a dijkstra-like issue)&lt;br /&gt;&lt;li&gt;An interesting article on the &lt;a href="http://www.webdesignerdepot.com/2010/02/20-years-of-adobe-photoshop/"&gt;history of photoshop&lt;/a&gt;, never realised how humble the beginnings were, and how much influence one mans decision to allow optional extras (ie: plug-ins) played on the future of the product.&lt;br /&gt;&lt;li&gt;I never realised this, but&lt;a href="http://mquandt.com/blog/2010/01/autodesk-student-subscriptions-freebies/"&gt;Autodesk has a massive price reduction for students&lt;/a&gt;, this includes 3ds Max, Maya, and AutoCAD. Wow!&lt;br /&gt;&lt;/ul&gt;And, as per usual, I'll finish off the catchup post with some neat videos. First, one that I think does a great job of explaining the animation process, and then a neat video showing just how far CG has come in film. (I recall speaking to &lt;a href="http://www.debevec.org/"&gt;Paul Debevec&lt;/a&gt; about Spiderman, and he said the director decided to redo all the actors in all scenes in CG since they looked better and they had more control over facial expressions,etc.)&lt;br /&gt;Cirkus Animation ABC:&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/O-qLBXIX2Mk&amp;hl=en_US&amp;fs=1&amp;"&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/O-qLBXIX2Mk&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;Stargate studios reel:&lt;object width="560" height="340"&gt;&lt;param name="movie" value="http://www.youtube.com/v/clnozSXyF4k&amp;hl=en_US&amp;fs=1&amp;"&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/clnozSXyF4k&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-3335661367948964486?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/3335661367948964486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=3335661367948964486' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3335661367948964486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/3335661367948964486'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/03/catchup-graphics-links-post.html' title='Catchup: Graphics Links Post'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-4109205706575762165</id><published>2010-02-19T17:55:00.000+08:00</published><updated>2010-02-19T17:55:20.091+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='compilers'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Profiling on Mac OSX with Saturn</title><content type='html'>It is always advisable to profile your code before trying to optimize it. It is often most helpful to role your own (using timers &amp;amp; counters), but often a quick and simple tool will help a lot.&lt;br /&gt;&lt;br /&gt;For windows I like the &lt;a href="http://www.codersnotes.com/sleepy"&gt;very sleepy&lt;/a&gt; profiler. On Mac OSX Apple provide the &lt;a href="http://developer.apple.com/tools/performance/overview.html"&gt;Saturn profiler&lt;/a&gt; (See: &lt;a href="http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/SaturnUserGuide/Introduction/Introduction.html"&gt;Saturn profiler user guide&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;To demonstrate we can try compiling a small program:&lt;br /&gt;&lt;pre&gt;#&lt;span style="color: blue;"&gt;include&lt;/span&gt; &amp;lt;math.h&amp;gt; &lt;br /&gt;#&lt;span style="color: blue;"&gt;include&lt;/span&gt; &amp;lt;stdio.h&amp;gt; &lt;br /&gt;&lt;br /&gt;#&lt;span style="color: blue;"&gt;include&lt;/span&gt; &amp;lt;saturn.h&amp;gt; &lt;span style="color: green;"&gt;//include the saturn profiler&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;double&lt;/span&gt; func1(&lt;span style="color: blue;"&gt;double&lt;/span&gt; x) { &lt;span style="color: green;"&gt;//do some maths&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;return&lt;/span&gt; sin(x)*cos(x); &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;double&lt;/span&gt; func2(&lt;span style="color: blue;"&gt;double&lt;/span&gt; x) { &lt;span style="color: green;"&gt;//do some more maths&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;return&lt;/span&gt; pow(x,&lt;span style="color: maroon;"&gt;3&lt;/span&gt;); &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;int&lt;/span&gt; main() { &lt;br /&gt;    &lt;span style="color: blue;"&gt;double&lt;/span&gt; x=&lt;span style="color: maroon;"&gt;0&lt;/span&gt;; &lt;br /&gt;    &lt;span style="color: blue;"&gt;double&lt;/span&gt; z=&lt;span style="color: maroon;"&gt;0&lt;/span&gt;; &lt;br /&gt;    startSaturn(); &lt;span style="color: green;"&gt;//being profiling&lt;/span&gt; &lt;br /&gt;    &lt;span style="color: blue;"&gt;for&lt;/span&gt; (x=&lt;span style="color: maroon;"&gt;0&lt;/span&gt;;x&amp;lt;&lt;span style="color: maroon;"&gt;100&lt;/span&gt;;x+=&lt;span style="color: maroon;"&gt;0&lt;/span&gt;&lt;span style="color: maroon;"&gt;.01&lt;/span&gt;) {&lt;br /&gt;        z+=func1(x)+func2(x)*tan(x); &lt;br /&gt;    } &lt;br /&gt;    stopSaturn(); &lt;span style="color: green;"&gt;//end profiling&lt;/span&gt; &lt;br /&gt;    printf(&lt;span style="color: maroon;"&gt;"z:%f\n"&lt;/span&gt;,z); &lt;span style="color: green;"&gt;//make sure compiler doesn't throw our computations away&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: maroon;"&gt;0&lt;/span&gt;; &lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now we need to compile it with profiling support:&lt;br /&gt;&lt;pre&gt;g++ x.c -finstrument-functions -lSaturn -m32 -O2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Some common problems include:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Undefined symbols: ___cyg_profile_func_enter&lt;br /&gt;&lt;/pre&gt;This comes from the -finstrument-functions option : it requires a special hook for each function - this is provided by saturn, so you must link with it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;ld: warning: in /usr/lib/libSaturn.dylib, file is not of required architecture&lt;br /&gt;Undefined symbols: _startSaturn&lt;br /&gt;&lt;/pre&gt;Again, either you forgot &lt;i&gt;-lSaturn&lt;/i&gt;, or you have remembered it, but are using a 64 bit OS/chip. Specify '-m32' to force 32bit mode.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;If it all compiled succesfully, then start Saturn and choose 'Saturn', 'Launch Process'. Then select the executable (eg: a.out) in the dialog box.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/S35fLIUGPMI/AAAAAAAAAPo/TUmhqba1Bjo/s1600-h/Screen+shot+2010-02-19+at+5.50.30+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/S35fLIUGPMI/AAAAAAAAAPo/TUmhqba1Bjo/s320/Screen+shot+2010-02-19+at+5.50.30+PM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Press OK, and Saturn will run and profile your program, and generate a folder with the profiler output data. (eg: Saturn_profile_a.out.000) &lt;br /&gt;&lt;br /&gt;You can then select the data file to view the output, and Saturn will display a call graph and the amount of time spent in each function. Now the fun of optimizing can begin. Enjoy!&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nHcDA3NyAms/S35f5AANC0I/AAAAAAAAAPw/sw5mD_Ix8hk/s1600-h/Screen+shot+2010-02-19+at+5.53.18+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_nHcDA3NyAms/S35f5AANC0I/AAAAAAAAAPw/sw5mD_Ix8hk/s320/Screen+shot+2010-02-19+at+5.53.18+PM.png" /&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/17188375-4109205706575762165?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/4109205706575762165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=4109205706575762165' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/4109205706575762165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/4109205706575762165'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/02/profiling-on-mac-osx-with-saturn.html' title='Profiling on Mac OSX with Saturn'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_nHcDA3NyAms/S35fLIUGPMI/AAAAAAAAAPo/TUmhqba1Bjo/s72-c/Screen+shot+2010-02-19+at+5.50.30+PM.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-6509117424864908146</id><published>2010-02-18T15:55:00.000+08:00</published><updated>2010-02-18T15:55:16.000+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><title type='text'>Intersection of a Convex Hull with a line segment</title><content type='html'>A ray, or line segment can be represented parametrically as:&lt;br /&gt;S(t) = A + t(B-A)&lt;br /&gt;Where A and B are the endpoints of the segment, and t is the parameter that ranges from –infinity to +infinity for a ray, or just 0..1 for a segment.&lt;br /&gt;&lt;br /&gt;A plane can be represented as n.X = d, where n is the plane’s normal, and d is the offset. (Given the plane’s normal, and a single point on the plane, P, we can calculate: d = -n.P)&lt;br /&gt;&lt;br /&gt;A convex object can be represented as the area contained within a set of planes. Thus, to find the intersection between a line segment and a convex object, we just need to clip it against all the planes that form the convex object.&lt;br /&gt;&lt;br /&gt;First, substitute the line equation into the plane, and solve for t:&lt;br /&gt;i.e.: &lt;br /&gt;n.(A+t(B-A)) = d&lt;br /&gt;n.A + t*n.(B-A) = d&lt;br /&gt;&lt;i&gt;note: using identity ru.sv = rs(u.v), where u,v are vectors, and r,s are scalars&lt;/i&gt;&lt;br /&gt;re-arrange to solve for t, the intersection point along the line:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/S3zxIwN26NI/AAAAAAAAAPI/tCEtbBcGO5M/s1600-h/convex1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="50" src="http://4.bp.blogspot.com/_nHcDA3NyAms/S3zxIwN26NI/AAAAAAAAAPI/tCEtbBcGO5M/s200/convex1.png" width="150" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;We can determine if the plane faces the segment or not by evaluating the dot product of the plane’s normal, and the line segment’s direction vector.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_nHcDA3NyAms/S3zxmfCI1sI/AAAAAAAAAPQ/9p-Xn5lbALQ/s1600-h/convex2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_nHcDA3NyAms/S3zxmfCI1sI/AAAAAAAAAPQ/9p-Xn5lbALQ/s320/convex2.png" /&gt;&lt;/a&gt;&lt;/div&gt;From this we can determine which point of an intersecting line segment to influence.  If the plane is facing the segment direction, then we can clip against the end point, otherwise we can clip against the start point. &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/S3zx5AC8ilI/AAAAAAAAAPY/PEjVCEG3uYQ/s1600-h/convex3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/S3zx5AC8ilI/AAAAAAAAAPY/PEjVCEG3uYQ/s320/convex3.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;As we are testing the intersection against a convex object we can simply keep clipping against each plane and altering the segment endpoints until we have the minimum remaining line length, or the intersection length becomes empty (there is no intersection).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_nHcDA3NyAms/S3zyOI3wBsI/AAAAAAAAAPg/73gqpYj9F7I/s1600-h/convex4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_nHcDA3NyAms/S3zyOI3wBsI/AAAAAAAAAPg/73gqpYj9F7I/s320/convex4.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;In pseudo-code the entire operation is:&lt;br /&gt;&lt;pre&gt;AB = B – A&lt;br /&gt;tFirst = 0&lt;br /&gt;tLast = 0&lt;br /&gt;for all planes:&lt;br /&gt; denom = N dot AB&lt;br /&gt; dist = d – N dot A&lt;br /&gt; t = dist/denom&lt;br /&gt; if (denom&gt;0 )&lt;br /&gt;  if (t&gt;tFirst) tFirst = t;&lt;br /&gt; else&lt;br /&gt;  if (t&lt;tLast) tLast = t;&lt;br /&gt; if (tFirst&gt;tLast)&lt;br /&gt;  No Intersection&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17188375-6509117424864908146?l=adrianboeing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://adrianboeing.blogspot.com/feeds/6509117424864908146/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17188375&amp;postID=6509117424864908146' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6509117424864908146'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17188375/posts/default/6509117424864908146'/><link rel='alternate' type='text/html' href='http://adrianboeing.blogspot.com/2010/02/intersection-of-convex-hull-with-line.html' title='Intersection of a Convex Hull with a line segment'/><author><name>Adrian</name><uri>http://www.blogger.com/profile/18234365657251895049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://3.bp.blogspot.com/_nHcDA3NyAms/Sgbk6yi7aPI/AAAAAAAAAEY/x4S8G9XHD8E/S220/profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nHcDA3NyAms/S3zxIwN26NI/AAAAAAAAAPI/tCEtbBcGO5M/s72-c/convex1.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17188375.post-2208532789097437223</id><published>2010-02-18T00:12:00.003+08:00</published><updated>2010-02-19T17:58:27.090+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><title type='text'>Solving Linear Systems</title><content type='html'>In school you probably learnt how to solve systems of linear equations with techniques like &lt;a href="http://en.wikipedia.org/wiki/Gaussian_elimination"&gt;Gaussian elimination&lt;/a&gt;, and &lt;a href="http://en.wikipedia.org/wiki/Row_echelon_form"&gt;Row-Reduced Echelon Form (RREF)&lt;/a&gt;. However a simple, brute-force way to &lt;a href="http://en.wikipedia.org/wiki/Iterative_m
