<?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-8309530329868152793</id><updated>2012-02-16T03:08:06.999-08:00</updated><category term='install'/><category term='Cortex Command'/><category term='Bresenham&apos;s Circle'/><category term='bug'/><category term='C'/><category term='post mortem kind of'/><category term='icns'/><category term='HLSL'/><category term='replay'/><category term='Math'/><category term='Unity3D'/><category term='Windows'/><category term='Xcode organiser'/><category term='softwareupdate'/><category term='separate'/><category term='Apple'/><category term='3.2.6'/><category term='SGE'/><category term='game development'/><category term='iphone'/><category term='IOS'/><category term='find ip'/><category term='Immediate Mode'/><category term='iee754'/><category term='Mac'/><category term='released'/><category term='cron'/><category term='c++'/><category term='wget'/><category term='OpenGL'/><category term='patch'/><category term='computation'/><category term='Darwin'/><category term='Lion'/><category term='Multi-platform'/><category term='certificates'/><category term='wee wee'/><category term='Unity 3D'/><category term='transferring'/><category term='Game Engine'/><category term='schedule'/><category term='Open GL'/><category term='floating point math'/><category term='JIRA Connection'/><category term='best practices'/><category term='OSX Lion'/><category term='Western Australia'/><category term='upcoming titles'/><category term='poop'/><category term='hate'/><category term='Developer'/><category term='diff'/><category term='school'/><category term='normal'/><category term='determinism'/><category term='OSX'/><category term='SDK'/><category term='Unity Asset Server'/><category term='batch'/><category term='split'/><category term='integration'/><category term='bandwidth'/><category term='new system'/><category term='kaka'/><category term='crap'/><category term='certificate'/><category term='Debug'/><category term='Perspective'/><category term='code sign'/><category term='error'/><category term='procedural mesh'/><category term='launchd'/><category term='Introduction'/><category term='Unix'/><category term='Bespoke'/><category term='Technology'/><category term='Xcode'/><category term='10.7'/><category term='suck'/><category term='split file'/><category term='shader'/><category term='poster child'/><category term='Simple'/><category term='Xbox 360'/><category term='ipad'/><category term='Studio'/><category term='view matrix'/><category term='asset server'/><category term='apple. osx'/><category term='Xcode 3.2.6'/><category term='apple mouse'/><category term='RunApplicationEventLoop'/><category term='offpeak'/><category term='projection matrix'/><category term='model matrix'/><category term='codesign'/><category term='valve'/><category term='dos'/><category term='code'/><category term='Derivation'/><category term='ico'/><category term='Unity Script'/><category term='Macintosh'/><category term='Joystick'/><category term='theory'/><category term='snippet'/><category term='Custom'/><category term='Games Development'/><category term='JIRA'/><category term='Updates'/><category term='Website'/><category term='stlport'/><category term='off peak'/><category term='convert'/><category term='programming'/><category term='pro'/><category term='magic mouse'/><category term='voip'/><category term='games'/><category term='careers'/><category term='size of string'/><category term='UnityScript'/><category term='API'/><category term='Eets'/><category term='CG'/><category term='Delegates'/><category term='tip'/><category term='Matrix'/><category term='Welcome'/><category term='C#'/><category term='developer profile'/><category term='business phone'/><category term='Carbon'/><category term='OSX 10.7'/><category term='net2max'/><category term='3D'/><category term='Linux'/><category term='Controller'/><category term='gcc'/><category term='GLSL'/><category term='steam'/><category term='command line'/><category term='mono'/><category term='Macros'/><category term='problem'/><category term='scheduling'/><title type='text'>Kruger Heavy Industries, Dev Log (of sorts)</title><subtitle type='html'>A chronicle of Kruger Heavy Industries and our adventures in games development, our games and industry noise.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>37</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-3713218597171014058</id><published>2011-12-08T19:57:00.001-08:00</published><updated>2011-12-11T22:12:33.215-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='integration'/><category scheme='http://www.blogger.com/atom/ns#' term='Unity 3D'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='JIRA Connection'/><category scheme='http://www.blogger.com/atom/ns#' term='patch'/><category scheme='http://www.blogger.com/atom/ns#' term='JIRA'/><category scheme='http://www.blogger.com/atom/ns#' term='diff'/><title type='text'>Unity3D iPhone Player and JIRA Connect Integration</title><content type='html'>We've been using JIRA internally for our project management and bug tracking for a couple of years now and we've found it to be excellent. Recently Atlassian (the developers of JIRA) released a JIRA Connect library for the iPad/iPhone family. &lt;br /&gt;&lt;br /&gt;If you are developing an iPad or iPhone application this library gives you application bug and error reporting, which integrates with JIRA for very little effort. &lt;br /&gt;&lt;br /&gt;Using JIRA Connect with Unity3D iPhone together in order to provide a nice way of automatically delivering crash reports and user feedback to your Unity application. For Unity users targeting the iPad/iPhone this quick little boon works for us to. Here is how to do it. &lt;br /&gt;&lt;br /&gt;At this point of this post I'm assuming you're familiar somewhat with JIRA and have a working JIRA instance, or are perhaps using the hosted JIRA solution offered by Atlassian (we much prefer to host our own - because we like control like that). &lt;br /&gt;&lt;br /&gt;In your JIRA instance; enable the JIRA Connect plugin, the JIRA Connect user and get your API Key from the Administration panel.&lt;br /&gt;&lt;br /&gt;Go and download the JIRA Connect source from &lt;a href="https://bitbucket.org/atlassian/jiraconnect-ios/downloads"&gt;here.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To get this integration working for Unity iPad/iPhone builds we're going to patch the Unity player source code that gets spat out &lt;br /&gt;by Unity when you make a Unity iPad/iPhone build.&lt;br /&gt;&lt;br /&gt;To have a starting position; make a Unity iPad/iPhone build now. Typically, if I have a project directory "ProjectName" I output my iPad/iPhone player build to "ProjectName_build". Generate this now.&lt;br /&gt;&lt;br /&gt;Unpack the JIRA Connect source code you have downloaded.&lt;br /&gt;&lt;br /&gt;At this point my directory looks like something like (I'm using OSX Lion)&lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;leberkaese: chriskruger$ ls&lt;br /&gt;atlassian-jiraconnect-ios-tip&lt;br /&gt;ProjectName&lt;br /&gt;ProjectName_build&lt;br /&gt;leberkaese: chriskruger$ &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Open the Xcode project file in your ProjectName_build directory in Xcode. I am using Xcode 4 btw. &lt;br /&gt;&lt;br /&gt;We are now going to make some changes to the project that Unity has spat out for us, in order to make use of JIRA Connect. We're basically following the instructions from &lt;a href="https://bitbucket.org/atlassian/jiraconnect-ios#readme"&gt;here.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So the steps as I see them for Xcode 4. &lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Add the JMCClasses directory to your Unity-iPhone/Classes group. Right click on the Classes group and choose to Add Files to Unity-iPhone. Browse to the atlassian-jiraconnect-ios-tip/JIRAConnect and choose the JMCClasses directory. Select to "make groups for any added folders" and press Add&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Select the Unity-iPhone project root in the project explorer, select the Unity-iPhone target and the Summary tab. Scroll down to the Linked Frameworks and Libraries. Add the following libraries for linking, CFNetwork, SystemConfiguration, MobileCoreServices, CoreGraphics, AVFoundation, CoreLocation, libsqlite&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-pGxLLRdPeWA/TuWZ6HLdcNI/AAAAAAAAAmg/9rKb1X2Gd9E/s1600/JMClassesView.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 259px; height: 310px;" src="http://1.bp.blogspot.com/-pGxLLRdPeWA/TuWZ6HLdcNI/AAAAAAAAAmg/9rKb1X2Gd9E/s320/JMClassesView.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5685119328263696594" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Choose the AppController.mm file in the Classes directory. We're going to edit this to integrate JIRA Connect. &lt;br /&gt;&lt;br /&gt;Near the top of AppController.mm we'll add the import statement &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-RxEDAQeBsgw/TuWaW16E1FI/AAAAAAAAAms/STG_CFQo4MQ/s1600/ImportJMC.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 84px;" src="http://3.bp.blogspot.com/-RxEDAQeBsgw/TuWaW16E1FI/AAAAAAAAAms/STG_CFQo4MQ/s320/ImportJMC.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5685119821843584082" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now move down further in the AppController.mm file and find the ApplicationDidFinishLaunching method. We're going to add the follow code in order to activate the library code when our application starts. Note that you'll need to alter this code from my example code in order for JIRA Connect to work with your JIRA instance. Specifically you'll need you JIRA instance's web address and it's API key. You might also want to change the configurations options to suit. &lt;br /&gt;&lt;br /&gt;When done applicationDidFinishLaunching will look something like this.&lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;pre&gt;&lt;br /&gt;- (void) applicationDidFinishLaunching:(UIApplication*)application&lt;br /&gt;{&lt;br /&gt; printf_console("-&gt; applicationDidFinishLaunching()\n");&lt;br /&gt;&lt;br /&gt;    JMCOptions* options = [JMCOptions optionsWithUrl:@"https://project.jira.com/"&lt;br /&gt;                                             project:@"PK"&lt;br /&gt;                                              apiKey:@"XXXXXXX-XXXXX-XXXX-XXX-XXXXXXXXXX"&lt;br /&gt;                                              photos:NO&lt;br /&gt;                                               voice:NO&lt;br /&gt;                                            location:NO&lt;br /&gt;                                       crashreporting:YES&lt;br /&gt;                                        customFields:nil];&lt;br /&gt;    &lt;br /&gt;    [[JMC instance] configureWithOptions:options];&lt;br /&gt;                        &lt;br /&gt;    &lt;br /&gt; if ([UIDevice currentDevice].generatesDeviceOrientationNotifications == NO)&lt;br /&gt;  [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];&lt;br /&gt;&lt;br /&gt; [self startUnity:application];&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;We were particularly interested in the crash reporting, so for the most part that's all we setup. &lt;br /&gt;&lt;br /&gt;So if you've done this. Check it all compiles and your Unity application still runs. &lt;br /&gt;&lt;br /&gt;If it all works we're now in a good position to generate some patches that we'll use to automatically update our Unity build from each time we make a build in Unity. &lt;br /&gt;&lt;br /&gt;Create another build outputting it to somewhere like ProjectName_build_vanilla.&lt;br /&gt;&lt;br /&gt;Create a some patches using diff. &lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;pre&gt;&lt;br /&gt;diff  -ru ProjectName_build_vanilla/Unity-iPhone.xcodeproj/project.pbxproj ProjectName_build/Unity-iPhone.xcodeproj/project.pbxproj &gt; xcode.patch&lt;br /&gt;&lt;br /&gt;diff -ru ProjectName_build_vanilla/Classes/AppController.mm ProjectName_build/Classes/AppController.mm &gt; AppController.patch&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Move these patches to ProjectName/Assets/Editor where they can easily be accessed during the Unity build process. &lt;br /&gt;&lt;br /&gt;Now we're going to modify the Unity build post process to apply our patches every time we make a build. So, if it doesn't already exist we will create a file called ProjectName/Assets/Editor/PostprocessBuildPlayer. This file is the standard way Unity permits modifications to the build pipeline.&lt;br /&gt;&lt;br /&gt;The contents of our PostprocessBuildPlayer file looks like.&lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;DIR=${0%/*}&lt;br /&gt;INSTALLPATH=${1}&lt;br /&gt;TARGET=${2}&lt;br /&gt;OPT=${3}&lt;br /&gt;COMPANY=${4}&lt;br /&gt;PRODUCT=${5}&lt;br /&gt;LOG=postprocess.txt&lt;br /&gt;&lt;br /&gt;echo "Postprocess Start" &amp;gt; ${LOG}&lt;br /&gt;echo "TARGET = ${TARGET}, PRODUCT = ${PRODUCT}" &amp;gt;&amp;gt; ${LOG}&lt;br /&gt;echo "INSTALLPATH = ${INSTALLPATH}" &amp;gt;&amp;gt; ${LOG}&lt;br /&gt;&lt;br /&gt;if [ $PRODUCT == "ProductName" ]&lt;br /&gt;then&lt;br /&gt;&lt;br /&gt;if [ "${TARGET}" == "iPhone" ]&lt;br /&gt;then&lt;br /&gt; echo "Applying patches for AppController and Xcode" &amp;gt;&amp;gt; ${LOG}&lt;br /&gt; (cd ${INSTALLPATH}; patch -N -p1 &amp;lt; ${DIR}/AppController.patch)  &lt;br /&gt; (cd ${INSTALLPATH}; patch -N -p1 &amp;lt; ${DIR}/xcode.patch)&lt;br /&gt;fi  &lt;br /&gt;&lt;br /&gt;fi&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It is just a quick and dirty bash script that applies our patches to the Unity iPad/iPhone player build every time we do a build. Once you've got this working you're now got JIRA Connect integrated into your Unity application.&lt;br /&gt;&lt;br /&gt;If you have trouble getting the JIRA Connect library working, define "DEBUG" in the build and the JIRA Connect library will log more information (to the Xcode console) about that it is trying to do when the application starts. This will help you work out what is wrong. &lt;br /&gt;&lt;br /&gt;Hope this works for you and please do lets us know if this guide needs updating/error correcting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-3713218597171014058?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/3713218597171014058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2011/12/unity3d-iphone-player-and-jira-connect.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/3713218597171014058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/3713218597171014058'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2011/12/unity3d-iphone-player-and-jira-connect.html' title='Unity3D iPhone Player and JIRA Connect Integration'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-pGxLLRdPeWA/TuWZ6HLdcNI/AAAAAAAAAmg/9rKb1X2Gd9E/s72-c/JMClassesView.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-133760369251971672</id><published>2011-10-20T20:05:00.000-07:00</published><updated>2011-10-20T20:35:31.982-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='projection matrix'/><category scheme='http://www.blogger.com/atom/ns#' term='Unity 3D'/><category scheme='http://www.blogger.com/atom/ns#' term='HLSL'/><category scheme='http://www.blogger.com/atom/ns#' term='view matrix'/><category scheme='http://www.blogger.com/atom/ns#' term='model matrix'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='GLSL'/><category scheme='http://www.blogger.com/atom/ns#' term='mono'/><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='Unity Script'/><category scheme='http://www.blogger.com/atom/ns#' term='shader'/><category scheme='http://www.blogger.com/atom/ns#' term='CG'/><category scheme='http://www.blogger.com/atom/ns#' term='Matrix'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='separate'/><category scheme='http://www.blogger.com/atom/ns#' term='pro'/><title type='text'>Unity 3D (Pro): View matrix (separately) for CG shaders</title><content type='html'>As Unity's shader support is largely based on Open GL, there isn't, by default design, access to separate model and view matrices in shader code. Occasionally you might want access to this and to use it you'll need to pass this information in yourself.&lt;br /&gt;&lt;br /&gt;Just a quick summary of what Unity does provide in Shader code.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;UNITY_MATRIX_MVP - Current model * view * project matrix&lt;/li&gt;&lt;br /&gt;&lt;li&gt;UNITY_MATRIX_MV - Current mode * view matrix&lt;/li&gt;&lt;br /&gt;&lt;li&gt;UNITY_MATRIX_P - Current project matrix&lt;/li&gt;&lt;br /&gt;&lt;li&gt;_Object2World - Current model matrix&lt;/li&gt;&lt;br /&gt;&lt;li&gt;_World2Object - Inverse of current world matrix&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Very occasionally I wish there was a UNITY_MATRIX_M and UNITY_MATRIX_V but there isn't - at least - not yet. (Same limitation in GLSL)&lt;br /&gt;&lt;br /&gt;In C# we can get the view matrix from &lt;b&gt;Camera.mainCamera.worldToCameraMatrix&lt;/b&gt; and for GameObjects the model matrix can be generated by using &lt;b&gt;Matrix4x4.TRS( transform.position, transform.rotation, transform.localScale)&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;If we wanted to pass in our own modelView matrix we could do &lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;Matrix4x4 modelViewMatrix = Camera.mainCamera.worldToCameraMatrix * Matrix4x4.TRS( transform.position, transform.rotation, transform.localScale);&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Then at the appropriate point we can do &lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;material.SetMatrix("modelView", modelViewMatrix);&lt;/pre&gt; &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;To pass this model view matrix into our shader. &lt;br /&gt;&lt;br /&gt;In our shader, presumably in the vertex shader we can then use this value like so&lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;v2f vert(appdata_base v) &lt;br /&gt;     {&lt;br /&gt;         v2f o;&lt;br /&gt;         o.pos = mul( mul(UNITY_MATRIX_P, modelView), v.vertex );&lt;br /&gt;         return o;&lt;br /&gt;     }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The result of the above code is exactly the same as &lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;o.pos = mul( UNITY_MATRIX_MVP, v.vertex );&lt;/pre&gt; &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So now knowing this you can manipulate and/or use the model and view matrices separately in your shaders if you so choose, by first passing them in from script code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-133760369251971672?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/133760369251971672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2011/10/unity-3d-pro-view-matrix-separately-for.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/133760369251971672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/133760369251971672'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2011/10/unity-3d-pro-view-matrix-separately-for.html' title='Unity 3D (Pro): View matrix (separately) for CG shaders'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-5977641897552181700</id><published>2011-10-11T17:45:00.000-07:00</published><updated>2011-10-11T18:15:00.973-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xcode organiser'/><category scheme='http://www.blogger.com/atom/ns#' term='new system'/><category scheme='http://www.blogger.com/atom/ns#' term='apple. osx'/><category scheme='http://www.blogger.com/atom/ns#' term='developer profile'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='error'/><category scheme='http://www.blogger.com/atom/ns#' term='bug'/><category scheme='http://www.blogger.com/atom/ns#' term='transferring'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='certificates'/><title type='text'>Moving iPhone Developer Credentials from one Mac to another</title><content type='html'>Update: So apparently in Xcode 4 (at least) there is an official way to do this... outlined &lt;href="http://developer.apple.com/library/ios/documentation/ToolsLanguages/Conceptual/Xcode4UserGuide/Devices/Devices.html#//apple_ref/doc/uid/TP40010215-CH12-SW16"&gt;here&lt;/href&gt;&lt;br /&gt;&lt;br /&gt;I recently reinstalled OSX on my Mac and upgraded to Lion. Of course I forgot to transfer my iPhone developer credentials before I did it. I had to go back to the provisioning portal and setup my new certificate and get a new developer profile. While it wasn't a huge time waste I should have transferred my certificates and profile to save myself some time.&lt;br /&gt;&lt;br /&gt;This is what I should have done. &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Open Xcode&lt;/li&gt;&lt;br /&gt;&lt;lil&gt;Window-&gt;Organizer&lt;/li&gt;&lt;br /&gt;&lt;li&gt;DEVELOPMENT -&gt; Provisioning Profiles&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Choose your Provisioning profile, right click and "Reveal in Finder"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Save the resulting file&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Open Keychain Access&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Export your private and public certificates to files and save them&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Transfer all the file to your new system&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Drag and drop Provisioning Profile into Xcode's Organiser on your new system&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Import the certificates file you exported into Keychain Access on your new system&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;NOTE: There is a very annoying bug in Keychain Access that means you need to re-import your certificates at the command line.  Attempting to you import you certificates using the Keychain Access GUI yields "An error has occurred. Unable to import an item. The contents of this item cannot be retrieved". This is just a blatant bug in Keychain Access you can import the files into Keychain Access at the command line with the following commands. &lt;br /&gt;&lt;br /&gt;&lt;code&gt;security import priv_key.p12 -k ~/Library/Keychains/login.keychain&lt;br /&gt;security import pub_key.pem -k ~/Library/Keychains/login.keychain&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-5977641897552181700?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/5977641897552181700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2011/10/moving-iphone-developer-credentials.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5977641897552181700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5977641897552181700'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2011/10/moving-iphone-developer-credentials.html' title='Moving iPhone Developer Credentials from one Mac to another'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-4791104208204574483</id><published>2011-08-04T23:26:00.000-07:00</published><updated>2011-08-04T23:40:51.887-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xcode 3.2.6'/><category scheme='http://www.blogger.com/atom/ns#' term='OSX'/><category scheme='http://www.blogger.com/atom/ns#' term='install'/><category scheme='http://www.blogger.com/atom/ns#' term='10.7'/><category scheme='http://www.blogger.com/atom/ns#' term='OSX 10.7'/><category scheme='http://www.blogger.com/atom/ns#' term='OSX Lion'/><category scheme='http://www.blogger.com/atom/ns#' term='3.2.6'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='Lion'/><title type='text'>Xcode 3.2.6 and OSX Lion (10.7) - Make it install</title><content type='html'>Today I enthusiastically installed OSX Lion on my development system. I was probably stupidly naive to think it would be a straightforward upgrade. &lt;br /&gt;&lt;br /&gt;Attempting to install Xcode 3.2.6, the version I currently prefer, it seemed to silently fail. I wasn't sure why. I did notice running the installation wizard; that at the point of selecting Installation Components the Xcode Tool Set component (Usually compulsory) was greyed out and marked as skip. &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-zvVx8wH6yvI/TjuQS-8C0II/AAAAAAAAAmA/JLaFrAiL8qY/s1600/Xcode_toolset_grey.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 232px;" src="http://3.bp.blogspot.com/-zvVx8wH6yvI/TjuQS-8C0II/AAAAAAAAAmA/JLaFrAiL8qY/s320/Xcode_toolset_grey.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5637258014391193730" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;After some research, It seems support for Xcode 3.2.6 on Lion is somewhat neglected as Xcode 4.x is the future. Long story short I needed to use 3.2.6. It can be motivated to install on Lion. &lt;br /&gt;&lt;br /&gt;After mounting the developer tools dmg you can open a terminal and issue the following commands to successfully install Xcode 3.2.6 on OSX Lion (10.7)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;export COMMAND_LINE_INSTALL=1&lt;br /&gt;open "/Volumes/Xcode and iOS SDK/Xcode and iOS SDK.mpkg"&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-4791104208204574483?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/4791104208204574483/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2011/08/xcode-326-and-osx-lion-107-make-it.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/4791104208204574483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/4791104208204574483'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2011/08/xcode-326-and-osx-lion-107-make-it.html' title='Xcode 3.2.6 and OSX Lion (10.7) - Make it install'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-zvVx8wH6yvI/TjuQS-8C0II/AAAAAAAAAmA/JLaFrAiL8qY/s72-c/Xcode_toolset_grey.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-1912285988251695827</id><published>2011-08-04T21:25:00.000-07:00</published><updated>2011-08-04T21:43:36.876-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='best practices'/><category scheme='http://www.blogger.com/atom/ns#' term='asset server'/><category scheme='http://www.blogger.com/atom/ns#' term='Unity Asset Server'/><category scheme='http://www.blogger.com/atom/ns#' term='Unity 3D'/><title type='text'>Unity3D Asset Server: Best Practice Workflow - Initial Checkout</title><content type='html'>Using Unity in teams one is often stuck using Unity asset server. While it certainly lacks features one has grown accustomed to in many other source control systems the fact remains that it is the solution that most seamlessly works with Unity. &lt;br /&gt;&lt;br /&gt;I think part of making the process of working with Unity Asset Server more enjoyable (apart form having experience with it) is to stick with some simple best practices. &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Checking out a Unity project for the first time&lt;/h2&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Find out what the project is called. You can do this looking looking at the server via another project.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;When opening Unity - choose to "Create new project". Give it the same name as the project is know by in asset server.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Open this new project and connect to the server (ALT-0 or CMD-0 depending on operating system) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Identify the project you are checking out and connect to it&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Choose to Update&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You'll be asked to make a decision about conflicting assets. Make sure you discard all existing files in the new project ("Discard My Changes"). This seems a little unintuitive but it makes sure you won't clutter your project or accidentally suck in unwanted files. &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-1912285988251695827?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/1912285988251695827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2011/08/unity3d-asset-server-best-practice.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/1912285988251695827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/1912285988251695827'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2011/08/unity3d-asset-server-best-practice.html' title='Unity3D Asset Server: Best Practice Workflow - Initial Checkout'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-7481379351007824410</id><published>2011-07-21T23:40:00.001-07:00</published><updated>2011-07-21T23:41:52.869-07:00</updated><title type='text'>Tell (automake) configure to use specific architecture on Mac OSX</title><content type='html'>Where we want to build 32 bit binary on OSX, and we know the codebase has a mix of C and C++ code.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;ARCHFLAGS="-arch i386" CFLAGS="-arch i386" CPPFLAGS="-arch i386" LDFLAGS="-arch i386" ./configure&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-7481379351007824410?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/7481379351007824410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2011/07/tell-automake-configure-to-use-specific.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/7481379351007824410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/7481379351007824410'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2011/07/tell-automake-configure-to-use-specific.html' title='Tell (automake) configure to use specific architecture on Mac OSX'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-9173677556328889590</id><published>2011-06-20T23:00:00.000-07:00</published><updated>2011-06-20T23:16:06.991-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code sign'/><category scheme='http://www.blogger.com/atom/ns#' term='problem'/><category scheme='http://www.blogger.com/atom/ns#' term='codesign'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='error'/><category scheme='http://www.blogger.com/atom/ns#' term='certificate'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='ipad'/><title type='text'>Xcode: iPhone or iPad application code sign error</title><content type='html'>This morning on a re-imaged OSX machine I attempted to compile an ipad application and I was rewarded with the error below.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;codesign error: code signing identity 'iphone developer' does not match any code-signing certificate in your keychain. once added to the keychain, touch a file or clean the project to continue.&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I was puzzled. I'd already made a developer certificate request to Apple, had it signed and installed it in my Keychain Access, I'd also downloaded and installed the &lt;b&gt;Apple Worldwide Developer Relations Certification Authority&lt;/b&gt; certificate. I'd installed the required development profile that matched my ipad device Unique Identifier, my personal developer certificate and the application I am developing but still, every time I hit build it gave me a code sign error. I didn't get it.&lt;br /&gt;&lt;br /&gt;At some point it a suspicion formed. In my Keychain Access I noticed my certificates where installed in the System keychain. I'm not even sure why they got installed there, I don't think I did it explicitly. &lt;br /&gt;&lt;br /&gt;I moved my certificates to the login keychain which I assume belongs to the logged in user on OSX (i.e. myself). Attempting to re-compile the source code of my ipad project yield a positive result. Moving the certificates to the login keychain seemed to work! So I post my small solution here today in the hope that somebody else might benefit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-9173677556328889590?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/9173677556328889590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2011/06/xcode-iphone-or-ipad-application-code.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/9173677556328889590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/9173677556328889590'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2011/06/xcode-iphone-or-ipad-application-code.html' title='Xcode: iPhone or iPad application code sign error'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-8160784053674762533</id><published>2011-06-16T18:25:00.000-07:00</published><updated>2011-06-16T19:25:27.592-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='theory'/><category scheme='http://www.blogger.com/atom/ns#' term='OSX'/><category scheme='http://www.blogger.com/atom/ns#' term='apple mouse'/><category scheme='http://www.blogger.com/atom/ns#' term='wee wee'/><category scheme='http://www.blogger.com/atom/ns#' term='poop'/><category scheme='http://www.blogger.com/atom/ns#' term='kaka'/><category scheme='http://www.blogger.com/atom/ns#' term='magic mouse'/><category scheme='http://www.blogger.com/atom/ns#' term='hate'/><category scheme='http://www.blogger.com/atom/ns#' term='suck'/><category scheme='http://www.blogger.com/atom/ns#' term='crap'/><title type='text'>Oh Magic Mouse! How do I hate thee.</title><content type='html'>While Apple have, over the years, had many design wins, there have also been some unfortunate design failures. The design failure that happens to torment me on a daily basis is Apple's Magic Mouse. Admittedly this bluetooth mouse is quite responsive and accurate as a pointing device, but it's the mouse's more esoteric features which are pimped as a unique selling point that really irk me. Namely the "multi touch surface", especially when used for scrolling. &lt;br /&gt;&lt;br /&gt;The multi touch surface is just far too sensitive and easily triggered when you're just using the mouse to move the pointer. As a coder I spend most of my day in text editors. I'm always accidentally scrolling the text window up and down; even worse - when using the command key and accidentally scrolling, the most common behaviour is to zoom. Not helpful. Give me an old fashioned scroll wheel any day. Likewise in a 3D modelling  package I often find myself accidentally zooming.&lt;br /&gt;&lt;br /&gt;It's back to the simple $20 mouse for me. On a similar note I have a theory about the efficacy of mice based on price. The sweet spot on mouse functionality is definitely around the $20 mark. Pay more and "features" get in the way. Pay less and accuracy, reliability and that comforting  solid hand weight quality possessed by a good mouse are absent.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-dnOLp6nz1Rc/Tfq69HH1ulI/AAAAAAAAAl4/WQukdr27yWc/s1600/graph.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 247px;" src="http://2.bp.blogspot.com/-dnOLp6nz1Rc/Tfq69HH1ulI/AAAAAAAAAl4/WQukdr27yWc/s320/graph.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5619009044144831058" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-8160784053674762533?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/8160784053674762533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2011/06/oh-magic-mouse-how-do-i-hate-thee.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/8160784053674762533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/8160784053674762533'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2011/06/oh-magic-mouse-how-do-i-hate-thee.html' title='Oh Magic Mouse! How do I hate thee.'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-dnOLp6nz1Rc/Tfq69HH1ulI/AAAAAAAAAl4/WQukdr27yWc/s72-c/graph.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-6789622393398327453</id><published>2011-06-14T05:35:00.000-07:00</published><updated>2011-06-14T18:53:11.629-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='softwareupdate'/><category scheme='http://www.blogger.com/atom/ns#' term='OSX'/><category scheme='http://www.blogger.com/atom/ns#' term='launchd'/><category scheme='http://www.blogger.com/atom/ns#' term='Updates'/><category scheme='http://www.blogger.com/atom/ns#' term='schedule'/><category scheme='http://www.blogger.com/atom/ns#' term='offpeak'/><category scheme='http://www.blogger.com/atom/ns#' term='off peak'/><title type='text'>Schedule Mac OSX Update(s) for Offpeak Download using launchd</title><content type='html'>In order to schedule you Mac OSX software update to run in Offpeak time you can use the launchd system scheduler in order to to accomplish this. On most Unix systems (including cousins and derivates like Mac OSX) you would use cron. While cron is still available on Mac OSX, Apple have provided an Apple centric way of doing the same the work in the form of launchd.&lt;br /&gt;&lt;br /&gt;Launchd has a command line control interface that goes by the name of launchctl, which will be using in conjuction with our xml editing skills to achieve this goal.&lt;br /&gt;&lt;br /&gt;The software update tool normally accessible via the Apple Menu (Apple-&gt;Software Update to be exact) has a command line parallel "softwareupdate". We can use this command line version to run the update in the background at suitably early hour of the morning.&lt;br /&gt;&lt;br /&gt;First of all lets construct a launchd configuration file to setup this job for us. In the common Mac OSX fashion this is achieved via the use of a property list file. Essentially an XML file with the information we want in it. A suitable .plist file for this work is listed below. Save this text into a file name like &lt;code&gt;com.krugerheavyindustries.SoftwareUpdate.plist&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;?xml&amp;nbsp;version=&amp;quot;1.0&amp;quot;&amp;nbsp;encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE&amp;nbsp;plist&amp;nbsp;PUBLIC&amp;nbsp;&amp;quot;-//Apple&amp;nbsp;Computer//DTD&amp;nbsp;PLIST&amp;nbsp;1.0//EN&amp;quot;&amp;quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;plist&amp;nbsp;version=&amp;quot;1.0&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;dict&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;key&amp;gt;Label&amp;lt;/key&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;string&amp;gt;com.krugerheavyindustries.SoftwareUpdate&amp;lt;/string&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;key&amp;gt;ProgramArguments&amp;lt;/key&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;array&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;string&amp;gt;/usr/sbin/softwareupdate&amp;lt;/string&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;string&amp;gt;--download&amp;lt;/string&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;string&amp;gt;--all&amp;lt;/string&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/array&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;key&amp;gt;StartCalendarInterval&amp;lt;/key&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;dict&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;key&amp;gt;Hour&amp;lt;/key&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;integer&amp;gt;2&amp;lt;/integer&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;key&amp;gt;Minute&amp;lt;/key&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;integer&amp;gt;00&amp;lt;/integer&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/dict&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;key&amp;gt;StandardErrorPath&amp;lt;/key&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;string&amp;gt;/var/log/software-update.log&amp;lt;/string&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;key&amp;gt;StandardOutPath&amp;lt;/key&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;string&amp;gt;/var/log/software-update.log&amp;lt;/string&amp;gt;&lt;br /&gt;&amp;lt;/dict&amp;gt;&lt;br /&gt;&amp;lt;/plist&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This particular property list configuration file schedules the software update to run at 2 am every morning.&lt;br /&gt;&lt;br /&gt;Now because this task is a system related task we need it to be run by the superuser in order to have sufficient privileges for this to happen. As this is the case I'd be storing this configuration file in &lt;code&gt;/Library/LaunchDaemon&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Next we load the configuration file in order to schedule it. We can accomplish this with superuser privileges by the doing the following: &lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo launchctrl load /Library/LaunchDaemon/com.krugerheavyindustries.SoftwareUpdate.plist&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;We can view the task is loaded and ready to roll by issuing:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo launchctl list | grep SoftwareUpdate&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;You should see the task there, if not, you might have a problem. &lt;br /&gt;&lt;br /&gt;The task will run every period you specified until you unload it (or reboot - we did not specify it should load itself). &lt;br /&gt;&lt;br /&gt;You can unload the task using the command: &lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo launchctl unload /Library/LaunchDaemon/com.krugerheavyindustries.SoftwareUpdate.plist&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;On a typically configured Mac, it will be setup to go to sleep if left on for a period of time. Obviously this will affect the running of your scheduled task. In order to make sure you schedule task will run I would schedule your machine to wakeup 5 minutes before the scheduled task is due to run. In this case at 1:55 AM. This just gives subsystems like WiFi time to reconnect to the wireless router.&lt;br /&gt;&lt;br /&gt;Sleep scheduling for wake up is done via Apple-&gt;System Preferences-&gt;Energy Saver-&gt;Schedule-&gt;Start or Wakeup&lt;br /&gt;&lt;br /&gt;When you come back to your system in the morning you should find your software updates ready to install. Replacing the keyword "--download" with "--install" in the property list file above you can get your updates to install (not just download) overnight also.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-6789622393398327453?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/6789622393398327453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2011/06/schedule-mac-osx-updates-for-offpeak.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/6789622393398327453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/6789622393398327453'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2011/06/schedule-mac-osx-updates-for-offpeak.html' title='Schedule Mac OSX Update(s) for Offpeak Download using launchd'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-374338911166461006</id><published>2011-01-27T05:20:00.000-08:00</published><updated>2011-01-27T05:44:59.838-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='careers'/><category scheme='http://www.blogger.com/atom/ns#' term='Math'/><category scheme='http://www.blogger.com/atom/ns#' term='poster child'/><category scheme='http://www.blogger.com/atom/ns#' term='school'/><category scheme='http://www.blogger.com/atom/ns#' term='Games Development'/><title type='text'>Games Development: A poster child for learning maths at school?</title><content type='html'>I catch the train to work most mornings. I get so much screen time every day I often like to zone out on the way to work. Driving, avoiding pedestrians and other cars cuts into my zone out time. The train works for me. I don't have to concentrate. I can look out the window, watch people and occasionally eavesdrops on some conversations people are having on the train. Yes, I'm kind of a sticky beak. &lt;br /&gt;&lt;br /&gt;The other morning I was largely alone in my section of the train. I was joined at the next stop by half-a-dozen teenage guys in school uniform on their way to school. In fairly typical teenage boy fashion they were talking loud, all pumped in the presence of their mates and talking about people they went to school with. &lt;br /&gt;&lt;br /&gt;After several topic changes which I couldn't follow (I don't think I'm across even half of what is 'street' these days) they settled on a conversation about how much maths sucks. &lt;br /&gt;&lt;br /&gt;Bigfoot zitty kid : "Maths is so lame. You never use that crap. Like algebra.. what are you going to ever use that for?"&lt;br /&gt;&lt;br /&gt;Sporty kid : "Yeah my dad reckons he's never used maths since he learned it, it's stupid - why do they even teach stuff like calculus. When the hell would you ever use that?" &lt;br /&gt;&lt;br /&gt;Nods of agreement all around. &lt;br /&gt;&lt;br /&gt;I didn't find it particularly surprising. In fact, I'm pretty sure I had a conversation just like that around the age of 15. &lt;br /&gt;&lt;br /&gt;What I did find ironic was the next topic of the conversation I was sneaky beaking on. They started talking about video games, and how cool it would be to make them. It struck me as ironic, because right there in front of them was a profession that actually used maths, and potentially quite heavily, to actually do things that are interesting to this demographic. It occurred to me right then - that Games Development is quite possibly the &lt;b&gt;perfect poster child career&lt;/b&gt; for demonstrating to kids what value you might actually get from learning maths.&lt;br /&gt;&lt;br /&gt;Modern games are using plenty of math. Every interaction on the screen is a cascade of vectors, linear algebra and geometry. You've often got some Newtonian Physics thrown in there for good measure too. &lt;br /&gt;&lt;br /&gt;I wanted to interject, but I resisted. I didn't want to blow my cover as the zoned out guy in the corner, I wanted to hear about what games they enjoyed playing. &lt;br /&gt;&lt;br /&gt;Chris K.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-374338911166461006?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/374338911166461006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2011/01/games-development-poster-child-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/374338911166461006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/374338911166461006'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2011/01/games-development-poster-child-for.html' title='Games Development: A poster child for learning maths at school?'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-3495162629821420452</id><published>2011-01-27T04:50:00.000-08:00</published><updated>2011-01-27T05:19:37.868-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='steam'/><category scheme='http://www.blogger.com/atom/ns#' term='OSX'/><category scheme='http://www.blogger.com/atom/ns#' term='post mortem kind of'/><category scheme='http://www.blogger.com/atom/ns#' term='released'/><category scheme='http://www.blogger.com/atom/ns#' term='Eets'/><title type='text'>Eets: Hunger it's Emotional - Released for Macintosh OSX</title><content type='html'>Somewhat belatedly we're pleased to announce the release of Eets: Hunger it's Emotional for OSX! It was released on Steam last December, and you can check it out &lt;a href="http://store.steampowered.com/app/6100/"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Whew. That was quite an effort for a small team like ours. It was a labour of love. While it's not the only thing we've worked on this past year, we've certainly taken our time when getting it done. &lt;br /&gt;&lt;br /&gt;While it is a port (for us) and the game content had already been completed since the release of the PC version it was still not a jobn for the faint of heart. &lt;br /&gt;&lt;br /&gt;Klei Entertainment when originally developing the game had not envisaged that the title would be destined for several other platforms. As such it was written largely in native windows APIs such as DirectX, Direct sound, windows threading and so on. There was little abtraction in the graphics, sound and IO layers. &lt;br /&gt;&lt;br /&gt;So we added all of that. We abstracted the graphics layer and put into place an OpenGL driver for the OSX port, we went through a similar process for sound support making use of OpenAL. For threading we just used pthreads for the most part. Perhaps we should have abstracted but we didn't in that case. The shaders were written in DirectX style assembly language and to move them over to OpenGL they were ported into HLSL.  &lt;br /&gt;&lt;br /&gt;Everytime we finish a title we're reminded of what it takes to actually finish a game. &lt;br /&gt;&lt;br /&gt;You feel like your done, when it's feature complete; the graphics and sound are working, the control system is squared away and yet - you're really just half way.&lt;br /&gt;We admit we felt like we'd finished when we reached this feature complete stage; we knew better intellectually but emotionally we fell for it all over again. &lt;br /&gt;&lt;br /&gt;At feature complete, you start the gruelling bug fixing stage. It's amazing how many bugs a few good testers can find. We had hundreds, many pretty small but it adds mountains of time to completion. After bug fixing, you then have to package and prep for distribution, this is also suprisingly time consuming. Sorting out distribution platforms quirks, further testing, prepping marking art, liasing with the publishers, partners, testers, reviewers and so on - and we had a lot of help. &lt;br /&gt;&lt;br /&gt;Nothing really beats the feeling of finish a title though. At least from our point of view. There is something deeply satisfying about it. I guess that's why we're in this business. &lt;br /&gt;&lt;br /&gt;We hope you enjoy Eets for OSX! We certainly enjoyed getting it out there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-3495162629821420452?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/3495162629821420452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2011/01/eets-hunger-its-emotional-released-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/3495162629821420452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/3495162629821420452'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2011/01/eets-hunger-its-emotional-released-for.html' title='Eets: Hunger it&apos;s Emotional - Released for Macintosh OSX'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-7281496839993362622</id><published>2010-12-24T05:44:00.001-08:00</published><updated>2010-12-29T17:47:04.903-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='split file'/><category scheme='http://www.blogger.com/atom/ns#' term='split'/><category scheme='http://www.blogger.com/atom/ns#' term='Xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='command line'/><category scheme='http://www.blogger.com/atom/ns#' term='wget'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><category scheme='http://www.blogger.com/atom/ns#' term='SDK'/><category scheme='http://www.blogger.com/atom/ns#' term='Developer'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='IOS'/><category scheme='http://www.blogger.com/atom/ns#' term='Macintosh'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='cron'/><category scheme='http://www.blogger.com/atom/ns#' term='scheduling'/><category scheme='http://www.blogger.com/atom/ns#' term='Website'/><title type='text'>Downloading files from the Apple Developer website using wget (for poor connections or scheduling)</title><content type='html'>Recently we had some issues downloading the latest iphone SDK. Firstly due to a crappy 3G broadband connection; we never seemed to be able to download the entire 3.5 Gigabyte file without a dropout. Unfortunately for us, Apple seem to have overlooked this possibility with their developer website and they do not offer the download using a more robust facility. Note to Apple. Ftp would be nice.&lt;br /&gt;&lt;br /&gt;Secondly with several team members located in the same city but not on the same LAN we wanted to distribute the update to all members via our shared linux server. Unfortunately, this said server is getting a little long in the tooth now and being a 32 bit linux distribution it does not support files of the size that is the Xcode and IOS dmg. We were going to have to split the file into more managable chunks. What a pain.&lt;br /&gt;&lt;br /&gt;The command line tool wget often yields answers to these kinds of problems so consequently it was our initial foray into finding a solution. Firstly it can provide an extra layer of robustness for downloading files, secondly it's very easy to schedule downloads via cron. For those of you wondering why this is a consideration - welcome to the reality of living in the internet 3rd world - Australia. With the typical internet plans in Australia, heavy internet users such as ourselves find it important to spread our download usage between peak periods (any time you're likely to be awake) and offpeak periods (any time you're likely to be sleeping) to maximise our bandwidth allocation.&lt;br /&gt;&lt;br /&gt;Frustratingly, downloading the IOS SDK via wget is complicated by the need for any web client connecting to the Apple Developer website to have been authenticated. The Apple website is known to use cookies to authenticate web clients, and several recipes for extracting authetication credentials from browser cookies into a file and using then via the wget command line interface are well known - at least for Firefox.&lt;br /&gt;&lt;br /&gt;The basic procedure for accessing content using wget from a site requiring authentication involves logging into the said site using a standard web browser, once authenticated via a login page one can set abou extracting the authentication cookie from the browser. The extracted cookie is then fed to wget which can use the cookie for permission to download the desired content.&lt;br /&gt;&lt;br /&gt;Being on a Macintosh system we are by default provided with Safari. Not bothering to install Firefox on every system one uses, we figured it was easier just to stick with Safari. Luckily the same technique can be performed with Safari as with Firefox. The technique for Safari  is not as well known as the Firefox technique, so we'll cover  it here.&lt;br /&gt;&lt;br /&gt;Safari stores its cookies on a per user basis within a user's home directory. Specifically cookies are stored in a simple XML file. Have a look in Library/Cookies/Cookies.plist. You can see all of Safari's cookies in there.&lt;br /&gt;&lt;br /&gt;To get the required cookie into the Cookies.plist before we proceed, use Safari to login to the Apple Developer Website using your Apple ID credentials. Safari should now have the requisite cookie. Opening the Cookies.plist with a text editor to view the cookie; we're looking for the one called ADCDownloadAuth.&lt;br /&gt;&lt;br /&gt;With wget expecting it's cookie information in the nescape cookie.txt file format we'd like a quick and simple way to convert from one format to the other. Luckily this is relatively easy to do on a Macintosh system. As the language Ruby is preinstalled on Tiger, Leopard and Snow Leopard systems we may as well leverage the language to do this job.&lt;br /&gt;&lt;br /&gt;Install the plist Ruby library and run the short ruby script listing below to convert the file to Firefox's cookies.txt format.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;$ sudo gem install plist&lt;br /&gt;$ irb&lt;br /&gt;&gt;&gt; require 'plist'&lt;br /&gt;&gt;&gt; result = Plist::parse_xml("Library/Cookies/Cookies.plist")&lt;br /&gt;&gt;&gt; File.open("cookies.txt", "w") {f result.each {r f.write("#{r["Domain"]}\tTRUE\t#{r["Path"]}\tFALSE\t#{r["Expires"].strftime("%s")}\t#{r["Name"]}\t#{r["Value"]}\n")}}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Now that we have our cookies.txt file we can download the file we would like. Note that the URL for the sdk was found by looking at Apple's Download website to see where the download link led.&lt;br /&gt;&lt;br /&gt;Below is the wget command line used to download the Xcode and iPhone SDK. Note that the command line variables for wget tell it to pipe the downloaded file to split which breaks the file up to make our venerable Linux file and webserver happy (2GB file limit). We're splitting the download into 512mb chunks here.&lt;br /&gt;&lt;br /&gt;To make sure the authetication works I needed to use the header flag and insert the cookie value at the command line. Looking at the cookie.txt file to again find the ADCDownloadAuth key and it's datavalue we place this data in exchange of the "XXX" marked command line below for this recipe to work.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;wget -qO- -U firefox -ct 0 --timeout=60 --waitretry=60 --load-cookies cookies.txt -c http://adcdownload.apple.com/ios/ios_sdk_4.2__final/xcode_3.2.5_and_ios_sdk_4.2_final.dmg --header="Cookie: ADCDownloadAuth=XXX" | split --bytes=512m - xcode_3.2.5_and_ios_sdk_4.2_final.dmg &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;You should now see your download commence and with everything to plan you'll have your dmg ready to install. You can ftp to you Macintosh. Once aboard you can &lt;br /&gt;&lt;code&gt;cat part1 part2 part3 ... &gt; combined.dmg&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In order to restore the split components. Happy Developing with the latest SDK!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-7281496839993362622?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/7281496839993362622/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/12/downloading-files-from-apple-developer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/7281496839993362622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/7281496839993362622'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/12/downloading-files-from-apple-developer.html' title='Downloading files from the Apple Developer website using wget (for poor connections or scheduling)'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-2609195694976574664</id><published>2010-08-31T04:59:00.000-07:00</published><updated>2010-09-03T20:00:41.744-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='game development'/><category scheme='http://www.blogger.com/atom/ns#' term='floating point math'/><category scheme='http://www.blogger.com/atom/ns#' term='determinism'/><category scheme='http://www.blogger.com/atom/ns#' term='replay'/><category scheme='http://www.blogger.com/atom/ns#' term='iee754'/><title type='text'>Game replay techniques and the importance of floating point determinism</title><content type='html'>&lt;p&gt;Working our way towards release we're currently going through a heavy bugfixing phase on the Macintosh version of Eets. One particularly interesting bug was causing incorrect level replays and the official solution video (not really videos but ingame replays) to be incorrect. We had a floating point determinism problem&lt;/p&gt;&lt;p&gt;Level completion replays and solution videos in Eets work by replaying user input. It makes a lot of sense to do this as user input is, relatively speaking, low frequency. To achieve the same results by recording the state of the all the objects in the game would make replay files a *lot* larger. (Consequently - The same technique can be used in writing a network game. Often known as the lockstep technique)&lt;/p&gt;&lt;p&gt;To be able to playback recorded user input into the game engine and have it play out exactly the same, the engine must be completely deterministic. A couple of key components needs to be addressed or things go very wrong.&lt;/p&gt;&lt;p&gt;For starters, the engine's random number generators are in fact not random at all. They need to play out the same random appearing numbers after being seeded each time. Secondly the mathematics of gameplay and engine need to be completely deterministic. This is actually not as easy as it sounds.&lt;/p&gt;&lt;p&gt;Next up, the physics engine needs to be designed from the beginning with determinism in mind. In particular iterative solvers are likely culprits for breaking determinism. Finally, the floating point math in all of it, needs to be deterministic. The floating point math situation is pontially one of the most tricky parts. Calls out to function in the operating system and other libraries - you frequently have not control over and they vary from platform to platform.&lt;/p&gt;&lt;p&gt;Once would think floating point math would always yield the same results, but the results actually vary slightly between processor, operating system, compiler and instruction set. Typically it's rounding method differences that are at play in this diverging scenario. (Did you know? - banking software avoids floats or doubles because of the way they handle rounding).&lt;/p&gt;&lt;p&gt;When floating point math was first catered for in silicon; a number of different ways of doing things made it out into the wild. The bulk of the computing public is using x86 type chips these days. In the early days of x86 floating point math was done in software, and understandably it was pretty slow. At some point the x87 co-processors were introduced. They were physically separate processors, and had their own instruction sets. Now the same instruction set exists today within your average Intel and AMD processor. It still gets used in software today but there are even more possibilities thrown into the mix. First came MMX (the multimedia instruction set), then MMX2, SSE, SSE2, and finally SEE3. Not to mention 3DNow and a similarly targeted instructions set. All of these instructions sets and their corresponding silicon implement floating point math in various ways and to varying degrees.&lt;/p&gt;&lt;p&gt;The Institute of Electrical and Electronic Engineers ratified a standard way of doing floating point math. The standard is known as ieee754. Making sure that your floating point math happens in a standardised way goes a long way to reducing the potential for different results.&lt;/p&gt;&lt;p&gt;Since most games engines update through time iteratively a small error early in the piece can create vastly different results down the track.&lt;/p&gt;&lt;p&gt;Mathematical methods like cos, tan and the other trigonometric functions are also common causes for different results on systems. The reason being that they're so called transcendental functions. That is they generate results by evaluating geometric series. Unfortunately this allows for plenty of scope for error.&lt;/p&gt;&lt;p&gt;Some tips on how to locate and improve floating point math determinism problems.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Use modern ieee754 compliant processor instruction sets SSE and up. Many compilers can be told to automatically use them for floating point math, otherwise you can manually use them via compiler intrinsics or assembly code.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Make sure you know what level of floating point optimisations are being using by the compiler when compiling. For the Microsoft Compilers look for problematic switches like /fp:fast. For gcc look for -mfpmath=sse and -msse and/or -msee2(x86 specific). &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Check results from Transcendental functions (tan, sin, cos and their ilk). If they're causing problems what in software versions outside of the system library that you have control over. &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/8309530329868152793-2609195694976574664?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/2609195694976574664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/08/game-replay-techniques-and-importance.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/2609195694976574664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/2609195694976574664'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/08/game-replay-techniques-and-importance.html' title='Game replay techniques and the importance of floating point determinism'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-4538719978722447055</id><published>2010-08-18T20:07:00.000-07:00</published><updated>2010-08-18T20:11:07.154-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='gcc'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Darwin'/><category scheme='http://www.blogger.com/atom/ns#' term='Macros'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>Howto to find out what gcc has as implicit defines</title><content type='html'>When dealing with portability and preprocessor issues while coding in C it is often very helpful to find out what all the default GCC compiler defined macros are. It's not immediately obvious how to see this. This is how you do it.&lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;gcc -dM -E - &lt; /dev/null&lt;br /&gt;&lt;/pre&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/8309530329868152793-4538719978722447055?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/4538719978722447055/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/08/howto-to-find-out-what-gcc-has-as.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/4538719978722447055'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/4538719978722447055'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/08/howto-to-find-out-what-gcc-has-as.html' title='Howto to find out what gcc has as implicit defines'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-2622784891701632795</id><published>2010-07-21T17:52:00.000-07:00</published><updated>2010-07-21T19:40:28.824-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Technology'/><category scheme='http://www.blogger.com/atom/ns#' term='Game Engine'/><category scheme='http://www.blogger.com/atom/ns#' term='Simple'/><category scheme='http://www.blogger.com/atom/ns#' term='SGE'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenGL'/><category scheme='http://www.blogger.com/atom/ns#' term='Multi-platform'/><title type='text'>Preview release of KHI 2D technology coming soon</title><content type='html'>With the release of Eets for Macintosh coming soon, our attention is slowly moving on to our next project in development. &lt;br /&gt;&lt;br /&gt;That as yet to be announced project is built upon a 2D engine that has been developed by ourselves.&lt;br /&gt;&lt;br /&gt;While our main goal has been to support the development of our next title, we have tried to build it in a general, clean and reusable way. We've also always hoped to be able to release the engine technology for other people to use and we intend to continue to build and maintain it. &lt;br /&gt;&lt;br /&gt;We're currently in the process of cleaning up an initial preview release of this technology. It's been tenatively named Simple Game Engine. It's an OpenGL based, accelerated, multi-platform 2D engine. Our initial goals we're to provide the following features to support the development of our game. &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;   &lt;li&gt;2D primitives&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;Accelerated via OpenGL&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;Loading of popular file types including, JPG, PNG, BMP, DDS and TGA&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;Multi-platform capability&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;Simple, easy to use API&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;Abstraction of native platform window and viewport handling&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;Usable from both C and C++ languages&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;Design with long term goal to support consoles&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;We're looking forward to sharing our initial preview release. WY6FHGGZUKB2&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-2622784891701632795?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/2622784891701632795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/07/preview-release-of-khi-2d-technology.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/2622784891701632795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/2622784891701632795'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/07/preview-release-of-khi-2d-technology.html' title='Preview release of KHI 2D technology coming soon'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-4515591293814139596</id><published>2010-07-06T05:10:00.000-07:00</published><updated>2010-07-13T04:53:01.879-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='gcc'/><category scheme='http://www.blogger.com/atom/ns#' term='Debug'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Unix'/><title type='text'>Separate debug symbols, just like Windows</title><content type='html'>Currently we're working heavily on Linux. You might ask why, but for now you'll have to wait to find out.&lt;br /&gt;&lt;br /&gt;Having become more familiar with heavy debugging under Linux we'd like to share with you a little tip about being able to ship binaries in a title that are still useful for debugging problems that are discovered out there in the wild.&lt;br /&gt;&lt;br /&gt;This is achievable under Linux by shipping debug binaries that have the debugging symbols separated from the binaries.&lt;br /&gt;&lt;br /&gt;Being able to do this under Windows is well known, in fact it's the default. Under Linux it's equally possible by using the less well know gcc debug-link functionality.&lt;br /&gt;&lt;br /&gt;This functionality is particularly useful when a distributed application dumps core on a user. One can get the core file, use the separate debugging information and see exactly where the application crashed. All you need to do when you make a build is put aside the separate debug files.&lt;br /&gt;&lt;br /&gt;Generally you don't want to distribute the debug symbols, for most people it's just a waste of space, and on the other hand it makes it easier for nefarious types to reverse engineer you code, or otherwise manipulate your software. &lt;br /&gt;&lt;br /&gt;This is potentially handy to many others, game developers or otherwise who are working under Linux.&lt;br /&gt; &lt;br /&gt;&lt;h4&gt;The How&lt;/h4&gt;&lt;br /&gt; &lt;br /&gt;Separating debug symbols from the main binary is achieved with using &lt;tt&gt;objcopy&lt;/tt&gt; which is part of the bintools package found on many Linux systems.&lt;br /&gt;&lt;br /&gt;We're particularly interested in the command line arguments &lt;tt&gt;--only-keep-debug&lt;/tt&gt;/&lt;tt&gt;--add-gnu-debuglink&lt;/tt&gt;&lt;br /&gt; &lt;br /&gt;&lt;h4&gt;What do these command line flags do?&lt;/h4&gt;&lt;br /&gt; &lt;br /&gt;&lt;tt&gt;--add-gnu-debuglink&lt;/tt&gt; adds a &lt;tt&gt;.gnu_debuglink&lt;/tt&gt; section to the binary. In that section is stored the name of debug file to look for.&lt;br /&gt; &lt;br /&gt;Below is a short shell transcript of how this is achieved:&lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ gcc -g -shared -o libtest.so libtest.c&lt;br /&gt;$ objcopy --only-keep-debug libtest.so libtest.dbg&lt;br /&gt;$ objcopy --add-gnu-debuglink=libtest.dbg libtest.so&lt;br /&gt;$ objdump -s -j .gnu_debuglink libtest.so&lt;br /&gt; &lt;br /&gt;libtest.so:     file format elf32-i386&lt;br /&gt; &lt;br /&gt;Contents of section .gnu_debuglink:&lt;br /&gt; 0000 6c696274 6573742e 64656275 67000000  libtest.debug...&lt;br /&gt; 0010 52a7fd0a                             R... &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt; &lt;br /&gt;The first part is the name of the file, the second part is a check-sum of debug-info file for later reference.&lt;br /&gt; &lt;br /&gt;&lt;h4&gt;Build ID&lt;/h4&gt;&lt;br /&gt; &lt;br /&gt;Did you know that binaries also get stamped with a unique id when they are built?  The &lt;tt&gt;ld&lt;/tt&gt; &lt;tt&gt;--build-id&lt;/tt&gt; flag stamps in a hash near the end of the link.&lt;br /&gt; &lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ readelf --wide --sections ./libtest.so  | grep build&lt;br /&gt;  [ 1] .note.gnu.build-id NOTE            000000d4 0000d4 000024 00   A  0   0  4&lt;br /&gt;$ objdump -s -j .note.gnu.build-id libtest.so &lt;br /&gt; &lt;br /&gt;libtest.so:     file format elf32-i386&lt;br /&gt; &lt;br /&gt;Contents of section .note.gnu.build-id:&lt;br /&gt; 00d4 04000000 14000000 03000000 474e5500  ............GNU.&lt;br /&gt; 00e4 a07ab0e4 7cd54f60 0f5cf66b 5799b05c  .z..|.O`.\.kW..\&lt;br /&gt; 00f4 2d43f456                             -C.V            &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;  &lt;br /&gt;Although the actual file may change (due to prelink or similar) the hash will not be updated and remain constant.&lt;br /&gt; &lt;br /&gt;&lt;h4&gt;Finding the debug info files&lt;/h4&gt;&lt;br /&gt; &lt;br /&gt;The last piece of the puzzle is how gdb attempts to find the debug-info files when it is run.  The main variable influencing this is the command &lt;tt&gt;debug-file-directory&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;After starting gdb, one can ... &lt;br /&gt; &lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(gdb) show debug-file-directory &lt;br /&gt;The directory where separate debug symbols are searched for is "/usr/lib/debug".&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt; &lt;br /&gt;The first thing gdb does, which you can verify via an strace, is&lt;br /&gt;search for a file called &lt;tt&gt;[debug-file-directory]/.build-id/xx/yyyyyy.dbg&lt;/tt&gt;; where xx is the first two hexadecimal digits of the hash, and yyy the rest of it:&lt;br /&gt; &lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ objdump -s -j .note.gnu.build-id /bin/ls&lt;br /&gt; &lt;br /&gt;/bin/ls:     file format elf32-i386&lt;br /&gt; &lt;br /&gt;Contents of section .note.gnu.build-id:&lt;br /&gt; 8048168 04000000 14000000 03000000 474e5500  ............GNU.&lt;br /&gt; 8048178 c6fd8024 2a11673c 7c6a5af6 2c65b1b5  ...$*.g&amp;lt;|jZ.,e..&lt;br /&gt; 8048188 d7e13fd4                             ..?.            &lt;br /&gt; &lt;br /&gt;... [running gdb /bin/ls] ...&lt;br /&gt; &lt;br /&gt;access("/usr/lib/debug/.build-id/c6/fd80242a11673c7c6a5af62c65b1b5d7e13fd4.debug", F_OK) = -1 ENOENT (No such file or directory)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt; &lt;br /&gt;Next it moves onto the debug-link info filename.  First it looks for the filename in same directory as the object being debugged. After that it looks for the file in a sub-directory called &lt;tt&gt;.debug/&lt;/tt&gt; in the same directory.&lt;br /&gt; &lt;br /&gt;Finally, it prepends the &lt;tt&gt;debug-file-directory&lt;/tt&gt; to the path of the object being inspected and looks for the debug info there. This is why the &lt;/tt&gt;/usr/lib/debug&lt;/tt&gt; directory looks like the root of a file-system; if you're looking for the debug-info of &lt;tt&gt;/usr/lib/libfoo.so&lt;/tt&gt; it will be looked for in &lt;tt&gt;/usr/lib/debug/usr/lib/libfoo.so&lt;/tt&gt;.&lt;br /&gt; &lt;br /&gt;Interestingly, the &lt;tt&gt;sysroot&lt;/tt&gt; and &lt;tt&gt;solib-search-path&lt;/tt&gt; don't appear to have anything to do with these lookups.  So if you change the sysroot, you also need to change the &lt;tt&gt;debug-file-directory&lt;/tt&gt; to match.&lt;br /&gt;&lt;br /&gt;Remember to keep the debug files for every build that gets distributed and you can load up the binary, core file and debug file all together and see exactly what happened.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-4515591293814139596?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/4515591293814139596/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/07/separate-debug-symbols-just-like.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/4515591293814139596'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/4515591293814139596'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/07/separate-debug-symbols-just-like.html' title='Separate debug symbols, just like Windows'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-2847697538301920277</id><published>2010-06-23T05:48:00.001-07:00</published><updated>2010-07-05T20:32:35.673-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='find ip'/><category scheme='http://www.blogger.com/atom/ns#' term='batch'/><category scheme='http://www.blogger.com/atom/ns#' term='dos'/><title type='text'>Find awake IP addresses on a subnet using a batch file</title><content type='html'>I seem to frequently find myself trying to find machines by IP address on a subnet. Often I'm on a random Windows machine and I've got nothing but the basic install to do it. What do I do? Good 'o batch script. You can find machines awake on a subnet using a script  like this. I might call it find_ip.bat&lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@echo off&lt;br /&gt;SET t=0&lt;br /&gt;:start&lt;br /&gt;SET /a t=t+1&lt;br /&gt;ping -n 1 -l 1 192.168.0.%t% &gt; nul&lt;br /&gt;if %errorlevel%==0 echo Host 192.168.0.%t% is UP!&lt;br /&gt;IF %t%==254 Exit&lt;br /&gt;Goto start&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Just substitute your IP subnet for 192.168.0.x and away you go.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-2847697538301920277?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/2847697538301920277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/06/find-awake-ip-addresses-on-subnet-using.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/2847697538301920277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/2847697538301920277'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/06/find-awake-ip-addresses-on-subnet-using.html' title='Find awake IP addresses on a subnet using a batch file'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-3105445730060467143</id><published>2010-04-23T01:35:00.000-07:00</published><updated>2010-07-07T17:50:04.507-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Unity 3D'/><category scheme='http://www.blogger.com/atom/ns#' term='normal'/><category scheme='http://www.blogger.com/atom/ns#' term='computation'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='procedural mesh'/><title type='text'>Unity 3D: A rough and ready computation of normals - useful for procedural meshes</title><content type='html'>Here is a rough and ready method to compute a meshes' vertex normals knowing the vertices and the indicies of your mesh. &lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  List&lt;Vector3&gt;[] normalBuffer= new List&lt;Vector3&gt;[NumVerts];&lt;br /&gt;  &lt;br /&gt;  for(int vl = 0; vl &lt; normalBuffer.Length; ++vl) {&lt;br /&gt;     normalBuffer[vl] = new List&lt;Vector3&gt;();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  for( int i = 0; i &lt; NumIndices; i += 3 )&lt;br /&gt;  {&lt;br /&gt;    // get the three vertices that make the faces&lt;br /&gt;    Vector3 p1 = m_original[m_mesh.triangles[i+0]];&lt;br /&gt;    Vector3 p2 = m_original[m_mesh.triangles[i+1]];&lt;br /&gt;    Vector3 p3 = m_original[m_mesh.triangles[i+2]];&lt;br /&gt;&lt;br /&gt;    Vector3 v1 = p2 - p1;&lt;br /&gt;    Vector3 v2 = p3 - p1;&lt;br /&gt;    Vector3 normal = Vector3.Cross(v1, v2 );&lt;br /&gt;&lt;br /&gt;    normal.Normalize();&lt;br /&gt;&lt;br /&gt;    // Store the face's normal for each of the vertices that make up the face.&lt;br /&gt;    normalBuffer[m_mesh.triangles[i+0]].Add(normal);&lt;br /&gt;    normalBuffer[m_mesh.triangles[i+1]].Add(normal);&lt;br /&gt;    normalBuffer[m_mesh.triangles[i+2]].Add(normal);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  for( int i = 0; i &lt; NumVerts; ++i )&lt;br /&gt;  {&lt;br /&gt;   for (int j = 0; j &lt; normalBuffer[i].Count; ++j) {&lt;br /&gt;    m_normals[i] += normalBuffer[i][j];&lt;br /&gt;   }&lt;br /&gt;    &lt;br /&gt;   m_normals[i]  /= normalBuffer[i].Count;&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&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/8309530329868152793-3105445730060467143?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/3105445730060467143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/04/unity-3d-rough-and-ready-computation-of.html#comment-form' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/3105445730060467143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/3105445730060467143'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/04/unity-3d-rough-and-ready-computation-of.html' title='Unity 3D: A rough and ready computation of normals - useful for procedural meshes'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-6512702125296218526</id><published>2010-04-14T00:22:00.000-07:00</published><updated>2010-07-07T17:52:31.655-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Unity 3D'/><category scheme='http://www.blogger.com/atom/ns#' term='Immediate Mode'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Unity 3D Immediate Mode: What's the trick with GL.modelview?</title><content type='html'>Unity 3D's immediate mode is really useful for debugging or adding a bit of chrome to a scene. While it's not the most efficient way of getting something on the screen it's so quick and handy. For those not using Unity 3D Pro. The GL namespace and functionality isn't available to you.&lt;br /&gt;&lt;br /&gt;Here's a little tip for setting the GL.modelview matrix so you can pump local space vertices into you GL.Vertex calls and have everything appear in the right spot.&lt;br /&gt;&lt;br /&gt;For example if I want to draw a line using model local space I need to setup the modelview matrix so GL primitives appear in the place in our 3D world.&lt;br /&gt;&lt;br /&gt;First of all we grab the scene camera using for example (using the C# API) :&lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;GameObject camera = GameObject.Find("Main Camera");&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Next we need to compose a matrix that will take into account the scene camera's position and the position of the model we're using. The final trick of composing this matrix is to convert from a Left handed co-ordinate system to a right handed co-ordinate system.&lt;br /&gt;&lt;br /&gt;Unity 3D normally uses a Left Handed camera co-ordinate system, where Z is postive leading out of the front of the camera. The underlying rendering system (originally designed on the Macintosh andOpenGL) is a Right Handed System (where Z is negative out of the Camera). The GL.modelview is expected to be in Right Handed. &lt;br /&gt;&lt;br /&gt;So to composite the correct modelview matrix we're going to first create a matrix to transform from a left handed to right handed system. We could do:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Matrix4x4 mat = Matrix4x4.identity;&lt;br /&gt;mat[2,2] *= -1.0f;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now we're ready to go, if we have the camera transform, the model tranforms and our conversion matrix. The result looks like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="codebox"&gt;&lt;br /&gt;&lt;pre&gt;GL.modelview = mat * (camera.transform.worldToLocalMatrix  * transform.localToWorldMatrix);&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now you can issue GL.Vertex3 commands in model local space&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-6512702125296218526?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/6512702125296218526/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/04/unity-3d-immediate-mode-what-trick-with.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/6512702125296218526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/6512702125296218526'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/04/unity-3d-immediate-mode-what-trick-with.html' title='Unity 3D Immediate Mode: What&apos;s the trick with GL.modelview?'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-3870031441883376326</id><published>2010-04-05T17:51:00.000-07:00</published><updated>2010-04-05T20:01:24.155-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='steam'/><category scheme='http://www.blogger.com/atom/ns#' term='valve'/><category scheme='http://www.blogger.com/atom/ns#' term='bandwidth'/><category scheme='http://www.blogger.com/atom/ns#' term='scheduling'/><category scheme='http://www.blogger.com/atom/ns#' term='schedule'/><category scheme='http://www.blogger.com/atom/ns#' term='offpeak'/><title type='text'>Schedule Steam (and use your Offpeak bandwidth)</title><content type='html'>Antipodeans get a raw deal when it comes to the Internet. It's expensive and slow, not to mention it's become a political hot potatoe with several poorly thought out schemes relating to the internet being pushed through in Canberra.&lt;br /&gt;&lt;br /&gt;Politics aside for now, that's not the reason for this post.&lt;br /&gt;&lt;br /&gt;With the core market for Valve's Steam service no doubt being the American market little attention was paid to download manager style features such as bandwidth throttling and scheduling. Valve's bandwidth heavy Cornocopia of Software can chew through the average Australian/NZ household's monthly bandwidth allocation in hours.&lt;br /&gt;&lt;br /&gt;Most Australian bandwidth plans have a Peak and Offpeak timesplit. Peak obviously falls into all those times you're likely to use the Internet. Unless you're a serious nightowl, at month's end you've probably still got a considerable amount of your Offpeak bandwidth allocation remaining.&lt;br /&gt;&lt;br /&gt;Steam doesn't offer built in download scheduling so here is a short recipe on how you can coax Stream to schedule a download for the Offpeak internet hours.&lt;br /&gt;&lt;br /&gt;I'm using Windows XP in this example, I can only assume it's similar for Vista and Windows 7.&lt;br /&gt;&lt;br /&gt;Firstly on the Login screen of Steam make sure you have the "remember password" option checked. You'll need to do this to allow Steam to automatically login and resume or initiate a download.&lt;br /&gt;&lt;br /&gt;Login in to steam initially, and go to the "My Games" tab and right click to "Install game..." on an undownloaded title you'd like to download and install. Steam will present you with details about the install, click next proceed. It will the process the file cache, and then ask you if you wish to create a shortcut to the desktop, which you should check (this is needed for later). The download will begin.&lt;br /&gt;&lt;br /&gt;Now that you've compleated the manual steps to setup the download, you can exit Stream. Once it's shutdown we can schedule the download for Offpeak hours. &lt;br /&gt;&lt;br /&gt;Go to your Desktop and find the shortcut you chose to create from Steam in the previous step. Right click on the shortcut and choose properties. You'll be presented with the shortcut properties. On this screen there will be a textbox labelled "Target". Highlight all the text in this textbox and copy it to your pasteboard. In this example the text I copied is (It's Half Life 2: Deathmatch):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;"c:\Program Files\Steam\steam.exe\" -applaunch 240&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Next choose Start-&gt;Run from the Main OS Menu, and type "cmd" in into the textbox presented in order to open a command window.&lt;br /&gt;&lt;br /&gt;We'll be using the command line command "schtasks" to schedule the Steam download.&lt;br /&gt;&lt;br /&gt;In the example below I've scheduled Steam to begin downloading at 2:00 AM in the morning. This is a typical Offpeak time, but you're might be different so you might want to check.&lt;br /&gt;&lt;br /&gt;Now we can construct the command line:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;schtasks /Create /TR "\"C:\Program Files\Steam\steam.exe\" -applaunch 240" /ST 02:00:00 /SC ONCE /TN Steam&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I've used the text I copied from the desktop shortcut as you can see. Pay special notice to the "\" characters I've inserted before the quotes. These are required to be able to input the whole command properly. &lt;br /&gt;&lt;br /&gt;The schtasks application should ask you for your user password to properly schedule Steam. If your user account doesn't have a password, you should probably set one. Typically schtasks won't run properly if you don't have a user password on your user account.&lt;br /&gt;&lt;br /&gt;You can see the scheduled task(s) by just running "schtasks". It's generally worth trying it first by running it in a minute or two's time to test it's all working properly. Just logout of Steam and reschedule to the appropriate time after you're satisfied.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-3870031441883376326?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/3870031441883376326/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/04/schedule-steam-and-use-your-offpeak.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/3870031441883376326'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/3870031441883376326'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/04/schedule-steam-and-use-your-offpeak.html' title='Schedule Steam (and use your Offpeak bandwidth)'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-5327284424875294029</id><published>2010-03-22T23:38:00.000-07:00</published><updated>2010-03-23T01:01:21.724-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='3D'/><category scheme='http://www.blogger.com/atom/ns#' term='projection matrix'/><category scheme='http://www.blogger.com/atom/ns#' term='Math'/><title type='text'>Derivation of the perspective matrix, Part 2</title><content type='html'>In part 2 of Derivation of a Perspective Matrix we look at the actual Matrix part.&lt;br /&gt;&lt;br /&gt;In part 1 we leaned how we map points inside our viewing frustum to points on our screen. From here we'd like to see how this becomes a perspective matrix.&lt;br /&gt;&lt;br /&gt;To move on I'd like to introduce the concept of the canonical view volume. The canonical view volume is the view volume (the visible area in front of the virtual camera) that is effectively scaled to fit nicely inside a volume where all x and y values are between [-1, 1], and the z values are between [0, 1]. By applying this scaling to points within the camera view volume it becomes trivial to test to see if points lie within the camera view.&lt;br /&gt;&lt;br /&gt;The reason we do a mapping from view volume to canonical view volume rather than a straight map to a plane is that we'd ideally like to be able to keep the Z value to be able to test for depth of a point within a scene. We can easily compare a point in canonical view volume space to another point in canonical view volume space to determine if one is potentially part of geometry that obscures other geometry. In modern computer graphics the process happens in the graphics driver, or indeed the graphics hardware, but it does explain the reasoning for the representation.&lt;br /&gt;&lt;br /&gt;The canonical view volume for a camera which demonstrates perspective looks like a pyramid with the top chopped off. You can see this shape easily in the original figure depicting the first part of the derivation. The only difference being that the canonical view volume is bounded in dimension in x and y by [-1, 1] and in z direction by [0, 1]. We've scaled all the values to meet this requirement. These space is called clipping space.&lt;br /&gt;&lt;br /&gt;At the end of Part1 we derived the formula to map eye space X to screen space X and eye space Y to screen space Y. In clipping space we keep the Z value.&lt;br /&gt;&lt;br /&gt;To go on we need to be familiar with the concept of the homogeneous co-ordinates. Homogeneous just means all of the same type/all-together/all the same. All the same of what? You might well ask. Lets start with the basics and refresh out memory about Euclidean space. Euclidean space is the maths we are familiar with when dealing with the basic math of points, vectors and lines. For computer graphics we normally deal with the 2 dimensional Cartesian plane, or the 3D dimensional “real coordinate space”. So Euclidean space co-ordinates are basically the mundane 2D and 3D co-ordinate systems we should all be familiar with by now. In 2D, we generally define the space using linearly independent axis denoted by x and y, and in 3D linearly independent axis x, y and z.&lt;br /&gt;&lt;br /&gt;Homogeneous coordinates refer to points in what is know as projective space. The mathematics of projective space is such that points and lines in projective space have corresponding points in Euclidean space. So the two spaces, Euclidean and Projective are connected by a relationship. Thus points in Projective space and Euclidean space can be converted from one to the other easily, and each point in one space has it's equivalent in another space. The word homogeneous in this case is referring to that equivalence.&lt;br /&gt;&lt;br /&gt;One particularly nice aspect of working in projective space is that if we are dealing with transformations using matrix mathematics we can create a 4 dimensional matrix that in practice is equivalent to a 3 dimensional euclidean space rotation matrix applied to a point, followed by a translation applied the same point.&lt;br /&gt;&lt;br /&gt;The other nicety of projective space for those working in computer graphics is that it's ideally suited to working with projections! Exactly what we're working on deriving here.&lt;br /&gt;&lt;br /&gt;Projective space has an additional coordinate. So a 2 dimensional euclidean point is represented by a 3 dimensional projective point and a 3 dimensional euclidean point is 4 dimensions in projective space. As we live in 3D dimensional meat space, the 4 dimensional part is impossible to visualize. It's probably better not to try. Suffice it to say the extra dimension is just providing an additional reference to identifying a point.&lt;br /&gt;&lt;br /&gt;There are a infinite projective space points that map to points in paired euclidean space, but the most basic and obvious representation of a point in euclidean space in projective space is the point where the projective (the additional co-ordinate) coordinate is 1. A point (x, y) in 2D Euclid becomes (x, y, 1) in projective space, and a point (x, y, z) becomes the point (x, y, z, 1) in projective space. The projective coordinate is typically represented by the letter w. When w = 1, the Euclid space coordinate is plain to see.&lt;br /&gt;&lt;br /&gt;As w is the projective coordinate the general rule for converting from homogeneous coordinates to euclidean coordinates is to use the projective coordinate to divide the other coordinates. (x, y, z, w) in projective space is (x/w, y/w, z/w) in euclidean space. Knowing this it is possible to see that a the projection space points (4, 2, 2, 1) and (8, 4, 4, 2) are the same point (4, 2, 2) in Euclidean space.&lt;br /&gt;&lt;br /&gt;Lets put down out equations for a conversion to clipping space from 3D eye space. For x and y they're pretty much the same as formulas for screen space.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_Fmx3P9hQJpA/S6hjbf7WQGI/AAAAAAAAAII/AGMi9ijQX2M/s1600-h/yclip_euclid.png"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 150px; HEIGHT: 72px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451716673010024546" border="0" alt="" src="http://2.bp.blogspot.com/_Fmx3P9hQJpA/S6hjbf7WQGI/AAAAAAAAAII/AGMi9ijQX2M/s320/yclip_euclid.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_Fmx3P9hQJpA/S6hjbOUezBI/AAAAAAAAAIA/nM1-u0FJdSQ/s1600-h/xclip_euclid.png"&gt;&lt;img style="WIDTH: 150px; HEIGHT: 90px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451716668283603986" border="0" alt="" src="http://1.bp.blogspot.com/_Fmx3P9hQJpA/S6hjbOUezBI/AAAAAAAAAIA/nM1-u0FJdSQ/s320/xclip_euclid.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We don't really have something for z part yet. We do know that we want to remove the dependence on z for our equations on the right hand side to create linear equations we can place into a matrix, so we'll multiply the equations through by z to leave our simple linear equation on the right hand side. We arrive with&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hlfjumvmI/AAAAAAAAAIY/QxXXKhAHC6E/s1600-h/yzclip_euclid.png"&gt;&lt;img style="WIDTH: 128px; HEIGHT: 128px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451718941773053538" border="0" alt="" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hlfjumvmI/AAAAAAAAAIY/QxXXKhAHC6E/s320/yzclip_euclid.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hlfcE_HlI/AAAAAAAAAIQ/z-I-Nxgtc4k/s1600-h/xzclip_euclid.png"&gt;&lt;img style="WIDTH: 150px; HEIGHT: 128px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451718939719442002" border="0" alt="" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hlfcE_HlI/AAAAAAAAAIQ/z-I-Nxgtc4k/s320/xzclip_euclid.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This might not look useful just yet, but bear with me. We've got these two formula mapping into some odd space thats a factor of z. Now we'd like to hang on to z co-ordinate. So we posit a point represented by&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hmPV-36rI/AAAAAAAAAIg/jmaSJQ8ZAvg/s1600-h/zclipz.png"&gt;&lt;img style="WIDTH: 64px; HEIGHT: 45px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451719762716912306" border="0" alt="" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hmPV-36rI/AAAAAAAAAIg/jmaSJQ8ZAvg/s320/zclipz.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So we're trying to find a matrix which maps the point (x, y, z) to to (Xclip*z, Yclip*z, Zclip*z). With (Xclip*z, Yclip*z, Zclip*z), since each term is dependent on z we can divide everything by z and end up with (Xclip, Yclip, Zclip) which is exactly what we want to find. So what we need first the in this matrix which maps between the two spaces. We've got the Xclip*z and Yclip*z component and are currently looking for the Zclip * z component. We know the formula will not be in any way dependent on x or y as the z axis is orthogonal to the plane of projection. Thus the most complicated it will be is a scalar multiplication of z with the possibly of a constant. So we're looking at something like&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_Fmx3P9hQJpA/S6hvwRvEKqI/AAAAAAAAAIw/o6nWrUAOpZI/s1600-h/zsolve.png"&gt;&lt;img style="WIDTH: 256px; HEIGHT: 128px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451730224117197474" border="0" alt="" src="http://4.bp.blogspot.com/_Fmx3P9hQJpA/S6hvwRvEKqI/AAAAAAAAAIw/o6nWrUAOpZI/s320/zsolve.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;where p and q are constants.&lt;br /&gt;&lt;br /&gt;We have a chance of working out what these constants will be because we know that our camera frustum is bounded by the near plane, and the far plane. We'd also like our screen space Zclip result to be scaled between the 0 and 1. This is a nice way to do it, and it's how 3D API's like OpenGL and DirectX work. So we've got some basic facts to work with.&lt;br /&gt;&lt;br /&gt;So we say that Zclip= 0 when z = D (near plane) and that Zclip = 1 when z = F (far plane).&lt;br /&gt;&lt;br /&gt;We've got Zclip = 0 when z = D so the right hand side of the equation will be zero. We can solve for q.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_Fmx3P9hQJpA/S6hw6yueEYI/AAAAAAAAAI4/qPu9PHxZ67Q/s1600-h/zsolvezero.png"&gt;&lt;img style="WIDTH: 128px; HEIGHT: 64px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451731504283390338" border="0" alt="" src="http://4.bp.blogspot.com/_Fmx3P9hQJpA/S6hw6yueEYI/AAAAAAAAAI4/qPu9PHxZ67Q/s320/zsolvezero.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_Fmx3P9hQJpA/S6hw7QNhvtI/AAAAAAAAAJA/ppl2XKap0NY/s1600-h/qequals.png"&gt;&lt;img style="WIDTH: 128px; HEIGHT: 64px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451731512198282962" border="0" alt="" src="http://1.bp.blogspot.com/_Fmx3P9hQJpA/S6hw7QNhvtI/AAAAAAAAAJA/ppl2XKap0NY/s320/qequals.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So lets do the same thing for when z = F&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hw7zldUZI/AAAAAAAAAJI/MfKWRq1rYx4/s1600-h/fequalspfplusq.png"&gt;&lt;img style="WIDTH: 128px; HEIGHT: 64px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451731521693897106" border="0" alt="" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hw7zldUZI/AAAAAAAAAJI/MfKWRq1rYx4/s320/fequalspfplusq.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We know what q is from the earlier step&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hw8HS8o5I/AAAAAAAAAJQ/KHhR3-ffLi8/s1600-h/fequalspfminuspd.png"&gt;&lt;img style="WIDTH: 128px; HEIGHT: 64px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451731526984967058" border="0" alt="" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hw8HS8o5I/AAAAAAAAAJQ/KHhR3-ffLi8/s320/fequalspfminuspd.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_Fmx3P9hQJpA/S6hxkv4LKnI/AAAAAAAAAJg/vRF1629UWuE/s1600-h/fequalsfminusdbyp.png"&gt;&lt;img style="WIDTH: 128px; HEIGHT: 64px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451732225073293938" border="0" alt="" src="http://4.bp.blogspot.com/_Fmx3P9hQJpA/S6hxkv4LKnI/AAAAAAAAAJg/vRF1629UWuE/s320/fequalsfminusdbyp.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_Fmx3P9hQJpA/S6hw8mXsxYI/AAAAAAAAAJY/pRmoiabonrY/s1600-h/pequalsfoverdminusf.png"&gt;&lt;img style="WIDTH: 128px; HEIGHT: 64px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451731535326397826" border="0" alt="" src="http://1.bp.blogspot.com/_Fmx3P9hQJpA/S6hw8mXsxYI/AAAAAAAAAJY/pRmoiabonrY/s320/pequalsfoverdminusf.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now we have a value for constant p and q that actually mean something, returning to our original equation and substituting yields&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_Fmx3P9hQJpA/S6hx9PR9aWI/AAAAAAAAAJo/Qytgwn2oRjQ/s1600-h/zclipbyz.png"&gt;&lt;img style="WIDTH: 128px; HEIGHT: 64px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451732645819804002" border="0" alt="" src="http://4.bp.blogspot.com/_Fmx3P9hQJpA/S6hx9PR9aWI/AAAAAAAAAJo/Qytgwn2oRjQ/s320/zclipbyz.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So we're left the equations&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hlfjumvmI/AAAAAAAAAIY/QxXXKhAHC6E/s1600-h/yzclip_euclid.png"&gt;&lt;img style="WIDTH: 128px; HEIGHT: 128px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451718941773053538" border="0" alt="" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hlfjumvmI/AAAAAAAAAIY/QxXXKhAHC6E/s320/yzclip_euclid.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hlfcE_HlI/AAAAAAAAAIQ/z-I-Nxgtc4k/s1600-h/xzclip_euclid.png"&gt;&lt;img style="WIDTH: 150px; HEIGHT: 128px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451718939719442002" border="0" alt="" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hlfcE_HlI/AAAAAAAAAIQ/z-I-Nxgtc4k/s320/xzclip_euclid.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_Fmx3P9hQJpA/S6hx9PR9aWI/AAAAAAAAAJo/Qytgwn2oRjQ/s1600-h/zclipbyz.png"&gt;&lt;img style="WIDTH: 128px; HEIGHT: 64px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451732645819804002" border="0" alt="" src="http://4.bp.blogspot.com/_Fmx3P9hQJpA/S6hx9PR9aWI/AAAAAAAAAJo/Qytgwn2oRjQ/s320/zclipbyz.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now if we move this calculation into projective space using homogeneous coordinates we can say we're writing a transform to . Normally we're write Ws = 1 for the most simple equivalence in projective space. Ok so if Ws equals 1 then we can see that&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_Fmx3P9hQJpA/S6hycIO7wCI/AAAAAAAAAJw/4J1ufa6LHlY/s1600-h/wclipbyz.png"&gt;&lt;img style="WIDTH: 128px; HEIGHT: 64px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451733176504008738" border="0" alt="" src="http://2.bp.blogspot.com/_Fmx3P9hQJpA/S6hycIO7wCI/AAAAAAAAAJw/4J1ufa6LHlY/s320/wclipbyz.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now we've got four equations we can put into a matrix yielding.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hypYFrKXI/AAAAAAAAAJ4/IHG3eb3Efbo/s1600-h/projmatrix1st.png"&gt;&lt;img style="WIDTH: 256px; HEIGHT: 256px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451733404098439538" border="0" alt="" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/S6hypYFrKXI/AAAAAAAAAJ4/IHG3eb3Efbo/s320/projmatrix1st.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So this matrix maps from euclidean point represented as a homogeneous coordinate (x, y, z, 1) to yield (XclipZ, YclipZ, ZclipZ, Z) as homogeneous coordinate, dividing through by z to create a euclidean coordinate yields (Xclip, Yclip, Zclip, 1). Our desired screen space coordinate.&lt;br /&gt;&lt;br /&gt;This current set of equations assumes a completely square view screen. If we take into account different possible aspect ratios we add the term for the aspect ratio. The aspect ratio defined as the view port width versus the hight. That is the width of the near plane (which we assume is our projection screen), versus the height of the near plane.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_Fmx3P9hQJpA/S6hzD0j4nfI/AAAAAAAAAKI/l05xnpTTqHs/s1600-h/aspectr.png"&gt;&lt;img style="WIDTH: 128px; HEIGHT: 64px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451733858417942002" border="0" alt="" src="http://2.bp.blogspot.com/_Fmx3P9hQJpA/S6hzD0j4nfI/AAAAAAAAAKI/l05xnpTTqHs/s320/aspectr.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We introduce this term into the equation for the Xs coordinate, and follow through to yield the matrix&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_Fmx3P9hQJpA/S6hzT0A6YfI/AAAAAAAAAKQ/ZPiE56vMfOE/s1600-h/projmatrix2nd.png"&gt;&lt;img style="WIDTH: 256px; HEIGHT: 256px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5451734133149164018" border="0" alt="" src="http://4.bp.blogspot.com/_Fmx3P9hQJpA/S6hzT0A6YfI/AAAAAAAAAKQ/ZPiE56vMfOE/s320/projmatrix2nd.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And here we have one common form of the projection matrix.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-5327284424875294029?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/5327284424875294029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/03/derivation-of-perspective-matrix-part-2.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5327284424875294029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5327284424875294029'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/03/derivation-of-perspective-matrix-part-2.html' title='Derivation of the perspective matrix, Part 2'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_Fmx3P9hQJpA/S6hjbf7WQGI/AAAAAAAAAII/AGMi9ijQX2M/s72-c/yclip_euclid.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-3729031922248241542</id><published>2010-02-10T18:32:00.000-08:00</published><updated>2010-02-14T17:42:19.470-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='OSX'/><category scheme='http://www.blogger.com/atom/ns#' term='Custom'/><category scheme='http://www.blogger.com/atom/ns#' term='Carbon'/><category scheme='http://www.blogger.com/atom/ns#' term='Bespoke'/><category scheme='http://www.blogger.com/atom/ns#' term='RunApplicationEventLoop'/><title type='text'>Your own Custom Carbon Application Event Loop</title><content type='html'>When one develops a Carbon API application, you normally just setup all your application callbacks and logic in your code before you hit the RunApplicationEventLoop call that doesn't return until you Quit. &lt;br /&gt;&lt;br /&gt;Certainly you can run different bits of code based on events and so on, and that works just fine for most cases. &lt;br /&gt;&lt;br /&gt;There are certain cases where this may not work for you and you want finer grained controls of when different bits and pieces of your code runs. You may wish you could get into the RunApplicationEventLoop and do things how you would like. If this sounds like you, then there is a way to do this.&lt;br /&gt;&lt;br /&gt;I needed this when porting a title to OSX, in order to give the same behaviour as the Windows build. Rather that work out how I could get it all to happen syncing between updates and renders I just implemented my own loop which gave me quick access to easy predictable control.&lt;br /&gt;&lt;br /&gt;Apple haven't told us exactly what happens in RunApplicationEventLoop but there is a way write your own loop that certainly has worked for folks so far. See the code below.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;static EventHandlerUPP gQuitEventHandlerUPP;   // -&gt; QuitEventHandler&lt;br /&gt;&lt;br /&gt;static OSStatus QuitEventHandler(EventHandlerCallRef inHandlerCallRef,&lt;br /&gt;         EventRef inEvent, void *inUserData)&lt;br /&gt;{&lt;br /&gt; OSStatus err;&lt;br /&gt;&lt;br /&gt; err = CallNextEventHandler(inHandlerCallRef, inEvent);&lt;br /&gt; if (err == noErr) {&lt;br /&gt;  *((Boolean *) inUserData) = true;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return err;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static OSStatus EventLoopEventHandler(EventHandlerCallRef inHandlerCallRef,&lt;br /&gt;           EventRef inEvent, void* inUserData)&lt;br /&gt;{&lt;br /&gt; OSStatus        err;&lt;br /&gt; OSStatus        junk;&lt;br /&gt; EventHandlerRef installedHandler;&lt;br /&gt; EventTargetRef  theTarget;&lt;br /&gt; EventRef        theEvent;&lt;br /&gt; Boolean         quitNow;&lt;br /&gt; static const EventTypeSpec eventSpec = {kEventClassApplication, kEventAppQuit};&lt;br /&gt;&lt;br /&gt; quitNow = false;&lt;br /&gt;&lt;br /&gt; // Install our override on the kEventClassApplication, kEventAppQuit event.&lt;br /&gt; err = InstallEventHandler(GetApplicationEventTarget(), gQuitEventHandlerUPP,&lt;br /&gt;        1, &amp;eventSpec, &amp;quitNow, &amp;installedHandler);&lt;br /&gt; if (err == noErr) {&lt;br /&gt;&lt;br /&gt;  // Run our event loop until quitNow is set.&lt;br /&gt;  theTarget = GetEventDispatcherTarget();&lt;br /&gt;  do {&lt;br /&gt;   err = ReceiveNextEvent(0, NULL, kEventDurationNoWait,&lt;br /&gt;          true, &amp;theEvent);&lt;br /&gt;   if (err == noErr) {&lt;br /&gt;    SendEventToEventTarget(theEvent, theTarget);&lt;br /&gt;    ReleaseEvent(theEvent);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /// Run application code&lt;br /&gt;   RunOurApplicationCodeHere();&lt;br /&gt;&lt;br /&gt;  } while ( ! quitNow );&lt;br /&gt;&lt;br /&gt;  junk = RemoveEventHandler(installedHandler);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return err;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;static void RunCustomApplicationEventLoop()&lt;br /&gt;{&lt;br /&gt; static const EventTypeSpec eventSpec = {'KWIN', 'KWIN' };&lt;br /&gt; OSStatus        err;&lt;br /&gt; OSStatus        junk;&lt;br /&gt; EventTargetRef  appTarget;&lt;br /&gt; EventHandlerRef installedHandler;&lt;br /&gt; EventRef        dummyEvent;&lt;br /&gt;&lt;br /&gt; dummyEvent = nil;&lt;br /&gt;&lt;br /&gt; err = noErr;&lt;br /&gt; if (gEventLoopEventHandlerUPP == nil) {&lt;br /&gt;  gEventLoopEventHandlerUPP = NewEventHandlerUPP(EventLoopEventHandler);&lt;br /&gt; }&lt;br /&gt; if (gQuitEventHandlerUPP == nil) {&lt;br /&gt;  gQuitEventHandlerUPP = NewEventHandlerUPP(QuitEventHandler);&lt;br /&gt; }&lt;br /&gt; if (gEventLoopEventHandlerUPP == nil || gQuitEventHandlerUPP == nil) {&lt;br /&gt;  err = memFullErr;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; if (err == noErr) {&lt;br /&gt;  err = InstallEventHandler(GetApplicationEventTarget(), gEventLoopEventHandlerUPP,&lt;br /&gt;         1, &amp;eventSpec, nil, &amp;installedHandler);&lt;br /&gt;  if (err == noErr) {&lt;br /&gt;   err = MacCreateEvent(nil, 'KWIN', 'KWIN', GetCurrentEventTime(),&lt;br /&gt;         kEventAttributeNone, &amp;dummyEvent);&lt;br /&gt;   if (err == noErr) {&lt;br /&gt;    err = PostEventToQueue(GetMainEventQueue(), dummyEvent,&lt;br /&gt;           kEventPriorityHigh);&lt;br /&gt;   }&lt;br /&gt;   if (err == noErr) {&lt;br /&gt;    RunApplicationEventLoop();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   junk = RemoveEventHandler(installedHandler);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; if (dummyEvent != nil) {&lt;br /&gt;  ReleaseEvent(dummyEvent);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;What this code does is that it creates a custom event loop that gets entered by the normal RunApplicationEventLoop when the event for it gets fired (very early on). The custom loop runs the normal events pump as expected. A custom quit event handler is inserted to toggle the finalisation of the custom event loop. Simple!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-3729031922248241542?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/3729031922248241542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/02/your-own-custom-carbon-loop.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/3729031922248241542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/3729031922248241542'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/02/your-own-custom-carbon-loop.html' title='Your own Custom Carbon Application Event Loop'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-5650400763173895541</id><published>2010-01-23T21:07:00.000-08:00</published><updated>2010-01-23T22:19:38.261-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OSX'/><category scheme='http://www.blogger.com/atom/ns#' term='Macintosh'/><category scheme='http://www.blogger.com/atom/ns#' term='ico'/><category scheme='http://www.blogger.com/atom/ns#' term='tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='icns'/><category scheme='http://www.blogger.com/atom/ns#' term='convert'/><title type='text'>Convert a Windows ico file to a Macintosh icns file</title><content type='html'>I needed to convert a Windows platform standard ico format icon file to a Macintosh icns format icon file and didn't find any quick relevant details via Google. &lt;br /&gt;&lt;br /&gt;Well, here is a little quick recipe for doing so without having to use any additional software, only what is already on your Macintosh. At least this worked just fine on my Leopard machine so it should at least be able to be done on Leopard and Snow Leopard. &lt;br /&gt;&lt;br /&gt;From the command line do the following, substituting in your relevant information. &lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;pookie:tmp admin$ sips -s format tiff icon.ico --out icon.tiff&lt;br /&gt;pookie:tmp admin$ tiff2icns -noLarge icon.tiff icon.icns&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-5650400763173895541?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/5650400763173895541/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/01/convert-windows-ico-file-to-macintosh.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5650400763173895541'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5650400763173895541'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/01/convert-windows-ico-file-to-macintosh.html' title='Convert a Windows ico file to a Macintosh icns file'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-368522664949108185</id><published>2010-01-15T19:56:00.000-08:00</published><updated>2010-01-15T20:36:20.512-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='Bresenham&apos;s Circle'/><category scheme='http://www.blogger.com/atom/ns#' term='Open GL'/><category scheme='http://www.blogger.com/atom/ns#' term='game development'/><title type='text'>Bresenham's circle, Open GL and blowing holes in textures</title><content type='html'>Bresenham's circle algorithm is actually a variation on Bresenham's line drawing algorithm and as such it gets it's name, even though Bresenham didn't really invent the circle part. &lt;br /&gt;&lt;br /&gt;Playing with destructable terrain I wanted to be able to blow circular holes in a texture. I succeeded by fetching a texture with Open GL and twiddling the bytes with the circle algorithm to do so. &lt;br /&gt;&lt;br /&gt;The code below is in the spirit of what I did. Below is the main meat method on the algorthim, you might call it DrawFilledCircle() or some such.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;..&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;&lt;br /&gt;Input Parameters: &lt;br /&gt;&lt;br /&gt;Vector2 pos;     // The position of the explosion/circle center in texture pixel space.  &lt;br /&gt;float       radius; // The radius of the explosion/circle in pixels &lt;br /&gt;unsigned char* buf; // The pixel array - pixels are in RGBA format&lt;br /&gt;Texture*  texure; // a texture or texture info pointer&lt;br /&gt;Colour      colour; // the colour RGBA that you want the circle to be&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;int width = texture-&gt;GetWidth();&lt;br /&gt;int height = texture-&gt;GetHeight();&lt;br /&gt; &lt;br /&gt;int left = int(pos.x - radius);&lt;br /&gt;int right = int(pos.x + radius);&lt;br /&gt;int top = int(pos.y + radius);&lt;br /&gt;int bottom = int(pos.y - radius);&lt;br /&gt;&lt;br /&gt;// check to see the circle will even touch the texture  &lt;br /&gt;if (!((left &lt; width &amp;&amp; right &gt; 0) &amp;&amp; (bottom &lt; height &amp;&amp; top &gt; 0))) &lt;br /&gt;{&lt;br /&gt; return;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int max_x = std::min(right, width);&lt;br /&gt;int max_y = std::min(top, height);&lt;br /&gt; &lt;br /&gt;int r = (int)radius;&lt;br /&gt;int x = 0;&lt;br /&gt;int y = r;&lt;br /&gt; &lt;br /&gt;float p = 1 - r;&lt;br /&gt; &lt;br /&gt;while (x &lt; y) &lt;br /&gt;{&lt;br /&gt; if (p &lt; 0)&lt;br /&gt; {&lt;br /&gt;         x += 1;&lt;br /&gt;  p = p + 2 * x + 1;&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  x += 1;&lt;br /&gt;  y -= 1;&lt;br /&gt;  p = p + 2 * (x - y) + 1;&lt;br /&gt; }&lt;br /&gt; CircleLineFill(buf, width, -x + pos.x, y + pos.y, x*2, colour, max_x, max_y);&lt;br /&gt; CircleLineFill(buf, width, -x + pos.x, -y + pos.y, x*2, colour, max_x, max_y);&lt;br /&gt; CircleLineFill(buf, width, -y + pos.x, x + pos.y, y*2, colour, max_x, max_y);&lt;br /&gt; CircleLineFill(buf, width, -y + pos.x, -x + pos.y, y*2, colour, max_x, max_y);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The next method is CircleLineFill. This is a slight variation of the normal algorithm that draws just the outline of a circle, it doesn't fill the circle. This method fills the entire circle, leaving the edges of the intersection with a black edge. &lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;void CircleLineFill((unsigned char* buf, int width, int x, int y, int length, Colour col, int max_x, int max_y))&lt;br /&gt;{&lt;br /&gt; if ((y &lt; 0 || y &gt;= max_y) ||&lt;br /&gt;  (x + length &lt; 0) ||&lt;br /&gt;  (x &gt;= max_x ))&lt;br /&gt;  return;&lt;br /&gt; &lt;br /&gt; int right = std::min(x + length - 1, max_x);&lt;br /&gt; int left = std::max(0, x + 1);&lt;br /&gt; &lt;br /&gt; Colour* pixel = NULL;&lt;br /&gt; if (x &gt;= 0)&lt;br /&gt; {&lt;br /&gt;  pixel = (Colour*)((char*)buf + (y * width * sizeof(Colour) + sizeof(Colour)*x));&lt;br /&gt;  if (pixel-&gt;a != 0)&lt;br /&gt;  {&lt;br /&gt;   *pixel = Colour(0, 0, 0, 255);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; int dwords = right - left;&lt;br /&gt; if (dwords &gt; 0)&lt;br /&gt; {&lt;br /&gt;  pixel = (Colour*)((char*)buf + (y * width * sizeof(Colour) + sizeof(Colour)*(left)));&lt;br /&gt;  memset(pixel, col.c, (dwords*sizeof(Colour)));&lt;br /&gt; }&lt;br /&gt; if (right &gt; 0 &amp;&amp; right &lt; max_x)&lt;br /&gt; {&lt;br /&gt;  pixel = (Colour*)((char*)buf + (y * width *  sizeof(Colour) + sizeof(Colour)*(right)));&lt;br /&gt;  if (pixel-&gt;a != 0) &lt;br /&gt;  {&lt;br /&gt;   *pixel = Colour(0, 0, 0, 255);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-368522664949108185?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/368522664949108185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/01/bresenhams-circle-open-gl-and-blowing.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/368522664949108185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/368522664949108185'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/01/bresenhams-circle-open-gl-and-blowing.html' title='Bresenham&apos;s circle, Open GL and blowing holes in textures'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-1928238595132345714</id><published>2010-01-12T21:34:00.000-08:00</published><updated>2010-01-12T21:46:38.617-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Unity 3D'/><category scheme='http://www.blogger.com/atom/ns#' term='Debug'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Byte Array to String in C# - Unity Debugging</title><content type='html'>While using C# and Unity, I found myself reading data straight from the network during (BinaryReader) a debugging session. &lt;br /&gt;&lt;br /&gt;I was trying to work out why data was sent correctly from the server, but was being interpreted so different on the Unity client. I could easily see what bytes (in hex format) were generated by the python server(with the very useful command line debugging ability), but on Unity I needed to think for a second to determine how to display bytes nicely in a hex format for my serialized object.&lt;br /&gt;&lt;br /&gt;The easiest way turned out to be as below.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;// example byte array read from a binary stream&lt;br /&gt;BinaryReader stream = new BinaryReader(buffer);&lt;br /&gt;byte[] byteArray = stream.ReadBytes(3);&lt;br /&gt;&lt;br /&gt;// import UnityEngine for Debug.Log&lt;br /&gt;Debug.Log(BitConverter.ToString(byteArray));&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The output looks like as follows&lt;br /&gt;&lt;code&gt;&lt;br /&gt;01-AB-CD&lt;br /&gt;UnityEngine.Debug:Log(Object)&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-1928238595132345714?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/1928238595132345714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2010/01/byte-array-to-string-in-c-unity.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/1928238595132345714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/1928238595132345714'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2010/01/byte-array-to-string-in-c-unity.html' title='Byte Array to String in C# - Unity Debugging'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-6325964803543615728</id><published>2009-12-06T20:31:00.000-08:00</published><updated>2010-01-21T15:04:53.770-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Unity 3D'/><category scheme='http://www.blogger.com/atom/ns#' term='size of string'/><category scheme='http://www.blogger.com/atom/ns#' term='UnityScript'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Compute Length of a String in Unity 3D</title><content type='html'>How to compute the length or size of a string in pixels wasn't immediately obvious to me in Unity 3D, which is why I thought I was quickly post how it can be done. Knowing the size of the string is often useful if you are developing your own complex controls of interfaces. It's also often commonly used for centering a string within a space. &lt;br /&gt;&lt;br /&gt;In order to compute the size of a rendered string, you will need your string and the GUI style with which you intend to render your string, and then finally a GUI content convenience object in order to pass the string into the CalcSize method of the GUIStyle object. See below for UnityScript pseudocode. &lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;/* declare the style and setup parameters with Unity 3D inspector */&lt;br /&gt;var guiStyle : GUIStyle; &lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;/* here is my string */&lt;br /&gt;var myString : String = "this is my string";&lt;br /&gt;&lt;br /&gt;/* create a content convenience object with which to pass the string */&lt;br /&gt;var myContent : GUIContent = new GUIContent();&lt;br /&gt;myContent.text = myString;&lt;br /&gt;&lt;br /&gt;/* CalcSize will return the dimensions (width and height) of the rendered string in pixels */ &lt;br /&gt;var stringSize : Vector2 = guiStyle.CalcSize(myContent);&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;You can then get the x and y components on the returned Vector2 for the size of the string in pixels, width and height. Remember, the font size, font type, spacing and all the rest of the GUIStyle parameters you configured in the Unity 3D inspector will alter the final pixel size values of the string.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-6325964803543615728?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/6325964803543615728/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2009/12/compute-length-of-string-in-unity-3d.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/6325964803543615728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/6325964803543615728'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2009/12/compute-length-of-string-in-unity-3d.html' title='Compute Length of a String in Unity 3D'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-5037875067652053324</id><published>2009-12-04T17:56:00.000-08:00</published><updated>2009-12-04T18:20:18.861-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='3D'/><category scheme='http://www.blogger.com/atom/ns#' term='Math'/><category scheme='http://www.blogger.com/atom/ns#' term='Derivation'/><category scheme='http://www.blogger.com/atom/ns#' term='Matrix'/><category scheme='http://www.blogger.com/atom/ns#' term='Perspective'/><category scheme='http://www.blogger.com/atom/ns#' term='Games Development'/><title type='text'>Derivation of the Perspective Matrix, Part 1</title><content type='html'>&lt;strong&gt;Preface &lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I have been wanting for some time to discuss in detail the Perspective Matrix. Not only do I find it an interesting topic but I have found numerous times during my career that it has helped to understand the Perspective Matrix and the math behind how it came into being. I'm not going to assume too much knowledge of the subject in this article so I'll start with the basics. Skip a bit if it's of no interest to you but I do hope that others will find this particular granularity of breakdown useful. I know it's been years since I've formally looked into the math behind this and I certainly befitted greatly from trying to explain how the perspective matrix works to others.&lt;br /&gt;&lt;br /&gt;While this piece is intended to be read all together I decided to break it up into several easy to digest parts more suitable to appearing on a development log. It's entirely possible I've made mistakes or omissions and I invite readers to point them out. I, like everybody, is learning all the time.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Part 1&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Since the gaming world went 3D the perspective matrix has come into it's element. Its the math which takes our 3D game world and displays it on our 2D televisions, monitors and screens. There are two common types of 3D projection, orthographic and perspective. Orthographic projection has it's place but for the most part it's perspective projection that does the heavy lifting in game titles.&lt;br /&gt;&lt;br /&gt;Artists have been aware of the phenomena of perspective for thousands of years. In particular with regards to the apparent relative size differences of objects depending on their distance from the viewer. A good artist depicts perspective intuitively and artistically.&lt;br /&gt;&lt;br /&gt;Over time mathematicians and natural scientists developed theories about perspective. The mathematics we use today seem to do a very good job of simulating perspective as we see it in the real world. Using linear algebra and the associated matrix math we can handily simulate a camera in our virtual 3D worlds.&lt;br /&gt;&lt;br /&gt;While we are in the moment less interested in orthographic projection it does serve to understand a little about it and it's differences to perspective projection. An orthographic projection will map a 3D point on to a 2D surface by modeling how the light travels from a 3D point to the 2D surface. The ray of light will intersect the projection surface orthogonally to that surface, in other words with a right angle – a perfect 90 degrees to the 2D surface. You could think of this as a lot like shadows projected on to a wall (an ray of anti-light if you like); as if you were playing with shadow puppets. The 2D surface will need to be at least as big as the 3D object in order to receive the projected rays at 90 degrees (in the natural world – in mathematics we are able to scale things).&lt;br /&gt;&lt;br /&gt;A camera, or an eye for that matter, is different, and a perspective projection will more accurately apply in this case. To understand why, one has to imagine what the light might be doing in order to reach the lens of the eye or camera. The viewing eye is quite small, so light that is viewed will be the light rays that will travel from the 3D point to the point where the eye is located. There is no condition on the light having to strike the 2D viewing surface orthogonally. In effect light will arrive at different angles on the 2D plane depending on its source distance and orientation. This is where the visual effect of perspective comes into existence. This is obviously simplified as an eye and a camera have a lens which changes the way the light travels, but we can ignore that for now.&lt;br /&gt;&lt;br /&gt;In your typical game, world co-ordinates are 3D co-ordinates relative to an arbitrary world origin. Camera or eye co-ordinates are 3D co-ordinates which are relative to an origin that is specified as being the position of the eye or camera.&lt;br /&gt;&lt;br /&gt;If we setup a little thought experiment and layout a diagram on paper or computer we can start to see where the mathematics will come from. Let us assume the geometry we're dealing with (points, lines and so on) has already been transformed from world co-ordinates to eye co-ordinates and that the projection plane is the same as the front clipping plane. It's not really relevant to this discussion so we'll ignore how that happens for now.&lt;br /&gt;&lt;br /&gt;If you reference the figure below you will be able to see how we imagine this model of our camera to be. A Right Handed Co-ordinate system is in place. We are using a viewing frustum aligned with the Z axis (the Z axis is relative to the eye so we subscript it with the lowercase e), with a near/front clipping plane at Ze = D, and far clipping &lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/Sxm_FkrxOYI/AAAAAAAAAGA/MEKKxyqftrQ/s1600-h/perspect_frustum.JPG"&gt;&lt;/a&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 366px; DISPLAY: block; HEIGHT: 154px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5411566529729870210" border="0" alt="" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/Sxm_FkrxOYI/AAAAAAAAAGA/MEKKxyqftrQ/s400/perspect_frustum.JPG" /&gt;plane at Ze = F, and the view angle we have represented by the half height of the frustum h. Note that the half height can also be represented by the viewing angle divided by 2. In this diagram we label the viewing angle with the lowercase Greek letter theta.&lt;br /&gt;&lt;br /&gt;Let us start by working through the transformation of a point in 3D space to a point in 2D space. For simplicity sake the 2D space we're talking about is our near clipping plane. If you like, what we project on here gets displayed onto our screen as a 2D image.&lt;br /&gt;&lt;br /&gt;As stated earlier we have agreed our 2D plane on which we are projecting is located at the near clip plane. If we want to be able to position points on this plane we need to give it a co-ordinate system of it's own. By convention this is known as screen space. Screen space being 2D will only have 2D co-ordinates, for simplicity we make the origin the center of the screen. In the figure above we can imagine it being the point at which the eye Z axis intersects our viewing plane.&lt;br /&gt;&lt;br /&gt;Using the mathematics of projection we can establish a projected 3D points position on the 2D plane by using the formula &lt;a href="http://1.bp.blogspot.com/_Fmx3P9hQJpA/Sxm_hQt8mjI/AAAAAAAAAGI/Fo3m7HYmoII/s1600-h/projection_x.JPG"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 64px; DISPLAY: block; HEIGHT: 46px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5411567005406632498" border="0" alt="" src="http://1.bp.blogspot.com/_Fmx3P9hQJpA/Sxm_hQt8mjI/AAAAAAAAAGI/Fo3m7HYmoII/s400/projection_x.JPG" /&gt;&lt;/a&gt;&lt;br /&gt;To understand this equation lets look at a more simple equation. The equation is Xss = Xe * D / Ze. It looks very much like the original formula above. What we see here is simply an application of the principle of similar triangles. If the angles of one triangle are equal to the angles of another triangle, then the triangles are said to be equiangular. These equiangular triangles have the same shape but may have different sizes. So equiangular triangles are also known as similar triangles. This principle is relevant here, if you look at the figure. This principle states that the ratio of the length of the sides of two triangle remains the same for similar triangles.&lt;br /&gt;&lt;br /&gt;This principle then allows us to see where Xss = Xe * D / Ze comes from. The two triangles we propose are similar are the triangle formed by the eye, a point on Xe and a point on Ze. The second triangle is the one formed by the eye, a point on Xs and the point D along the Ze axis. We can see they are similar triangles so thus the length ratio between the sides from the eye to D and Eye to Ze will be the same ratio between eye to Xe and screen origin to Xs. Knowing this ratio we simply multiply the ratio by the length of the side we do know about on the other triangle, yielding the length of the side we're interested in which happens to be Xss.&lt;br /&gt;&lt;br /&gt;So now we understand where we get the first part of the projection, the part for the X axis at least. The same principle works exactly the same along the Y axis.&lt;br /&gt;&lt;br /&gt;That part was straightforwards enough, but we know that we're still missing the h term from our simplified formula. Now lets look at where the half height of the screen comes in to the equation. The half height of the screen is another way of expressing the field of view of the camera. The field of view of the camera we signify in this example as the angle theta. It is easy to see that if we increase the value of h the screen area we have for projecting on to is much larger. Dividing Xe * D / Ze by h will yield Xs as a value in screen space.&lt;br /&gt;&lt;br /&gt;Using basic trigonometry we can see that&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_Fmx3P9hQJpA/SxnAhDX-kqI/AAAAAAAAAGY/kGA2zKB7zT4/s1600-h/trig_tan.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 128px; height: 70px;" src="http://2.bp.blogspot.com/_Fmx3P9hQJpA/SxnAhDX-kqI/AAAAAAAAAGY/kGA2zKB7zT4/s400/trig_tan.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5411568101336453794" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_Fmx3P9hQJpA/SxnAVgr3CxI/AAAAAAAAAGQ/JjBfRsXW8uY/s1600-h/trig_tan.JPG"&gt;&lt;/a&gt;&lt;br /&gt;So substituting this back into our equation we get&lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/SxnA_T1izEI/AAAAAAAAAGg/dJepWkVBTpc/s1600-h/proj_x_w_tan.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 128px; height: 48px;" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/SxnA_T1izEI/AAAAAAAAAGg/dJepWkVBTpc/s400/proj_x_w_tan.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5411568621151505474" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;which becomes&lt;a href="http://1.bp.blogspot.com/_Fmx3P9hQJpA/SxnCQHlxVlI/AAAAAAAAAG4/B4GFTnOq0jE/s1600-h/proj_x_red.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 128px; height: 64px;" src="http://1.bp.blogspot.com/_Fmx3P9hQJpA/SxnCQHlxVlI/AAAAAAAAAG4/B4GFTnOq0jE/s320/proj_x_red.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5411570009433527890" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;and this for our Y axis component &lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/SxnBZ9VEvFI/AAAAAAAAAGw/OFRtATMibmA/s1600-h/proj_y_red.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 128px; height: 64px;" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/SxnBZ9VEvFI/AAAAAAAAAGw/OFRtATMibmA/s400/proj_y_red.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5411569078966205522" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So here have arrived at two simple equations for projection of a point on to the 2D plane we've decided is our screen. We can use our equations from this position in our journey to do more, which I'll cover in part 2.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-5037875067652053324?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/5037875067652053324/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2009/12/derivation-of-perspective-matrix-part-1.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5037875067652053324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5037875067652053324'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2009/12/derivation-of-perspective-matrix-part-1.html' title='Derivation of the Perspective Matrix, Part 1'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Sxm_FkrxOYI/AAAAAAAAAGA/MEKKxyqftrQ/s72-c/perspect_frustum.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-7011817883087207771</id><published>2009-11-10T17:00:00.000-08:00</published><updated>2009-11-11T01:18:10.801-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='OSX'/><category scheme='http://www.blogger.com/atom/ns#' term='Macintosh'/><category scheme='http://www.blogger.com/atom/ns#' term='tip'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='stlport'/><title type='text'>An stlport tip, for solving linker errors (stlpmtx_std vs stlp_std)</title><content type='html'>We've been making heavy use of stlport for our projects. Stlport is a great, freely available library that one can use on plaforms without a mature C++ stl library. A number of our team experienced problems when building an stlport application; specifically linker errors.&lt;br /&gt;&lt;br /&gt;A common cause of link errors while making use of STLPort is variations in the compile flags between the stlport library itself (if it needed to be compiled - often it's headers only, depending on how you use it) and the applicaton. &lt;br /&gt;&lt;br /&gt;With the output errors, check the namespace of the missing methods, it might tell you something about what's happening. The specific problem occuring for members of our team was yielding errors with a signature of form:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;stlpmtx_std::methodname&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Eventually we realized the application was compiled with stlport in a non thread safe form (i.e. _NOTHREADS defined), but my the systems' dynamic libraries (of stlport) were compiled as thread safe (generating the corresponding link table name prefix signature - stlp_std::methodname).&lt;br /&gt;&lt;br /&gt;Hopefully this will help somebody who might be confused or stumped with the same issue.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-7011817883087207771?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/7011817883087207771/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2009/11/stlport-tip-for-solving-linker-errors.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/7011817883087207771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/7011817883087207771'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2009/11/stlport-tip-for-solving-linker-errors.html' title='An stlport tip, for solving linker errors (stlpmtx_std vs stlp_std)'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-5900235376619079036</id><published>2009-11-03T09:51:00.000-08:00</published><updated>2009-11-03T17:55:55.402-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cortex Command'/><category scheme='http://www.blogger.com/atom/ns#' term='OSX'/><category scheme='http://www.blogger.com/atom/ns#' term='Macintosh'/><category scheme='http://www.blogger.com/atom/ns#' term='Controller'/><category scheme='http://www.blogger.com/atom/ns#' term='Joystick'/><category scheme='http://www.blogger.com/atom/ns#' term='Xbox 360'/><title type='text'>Use a Xbox 360 Controller with Cortex Command on the Macintosh</title><content type='html'>As you may know Kruger Heavy Industries brought Cortex Command to the Macintosh. It was a work of love, and continues to be as Cortex Command works it's way up to being content complete (and finally finished). We work on a build now and then and when Data Realms is finally satisfied the game is complete we'll have many more avenues available to us to promote and distribute the game. Many magazines and stores understandably won't stock or promote unfinished products.&lt;br /&gt;&lt;br /&gt;In the mean time I wanted to mention one cool thing about the Macintosh version of Cortex Command that I don't think many people are aware of. It's possible to use a Xbox 360 controller with Cortex Command, and the experience is greatly benefited for it.&lt;br /&gt;&lt;br /&gt;Cortex Command was from the outset designed with consoles in mind. From the circular menu systems allowing for easy option selection with a D-pad or joystick, to the targeting system that remains easy to work with a joystick it was always a design consideration. Data Realms hopes to bring this title to a console one day. As do we.&lt;br /&gt;&lt;br /&gt;So for Cortex Commanders why not play the game as it was intended - with a console controller.&lt;br /&gt;&lt;br /&gt;Microsoft have had available for the purchase the "Xbox 360 Controller for Windows" for some time now. It's basically identical to your typical wired Xbox 360 controller but comes with the Windows driver CD. If you don't have an Xbox 360, this is probably the easiest way to get a hold of a controller.&lt;br /&gt;&lt;br /&gt;For a wired Xbox 360 Controller, it's just USB. Plug it into your Macintosh and it's ready to use.&lt;br /&gt;&lt;br /&gt;For those with Xbox 360 Wireless controllers you can get a PC receiver for you Xbox 360 wireless controller. There is a brief description &lt;a href="http://support.xbox.com/support/en/us/nxe/kb.aspx?ID=933711&amp;amp;lcid=1033&amp;amp;category=hardware"&gt;here&lt;/a&gt;. It just plugs into your USB port and they're relatively available. Note however, that it's probably cheaper just to buy a wired controller for windows. Depends on how much you value your wirelessness (I think I made that word up).&lt;br /&gt;&lt;br /&gt;So once you have yourself a controller we can use it on the Macintosh thanks to Tattie Bogle who wrote the driver for Macinosh OSX. You can find out about it and fetch it from &lt;a href="http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller"&gt;here&lt;/a&gt;. I believe it now supports both the Wired controller and the Wireless Controller.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_Fmx3P9hQJpA/SvDZ9Z4ehlI/AAAAAAAAAEg/_HuPWDjXAQI/s1600-h/controller_driver_dl.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 350px; height: 74px;" src="http://2.bp.blogspot.com/_Fmx3P9hQJpA/SvDZ9Z4ehlI/AAAAAAAAAEg/_HuPWDjXAQI/s400/controller_driver_dl.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5400055602160240210" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Install the Xbox 360 controller driver and then you can insert you controller into the USB port of your Macintosh. If you go to the controller options via the Apple menu you can open up the controller calibration settings. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_Fmx3P9hQJpA/SvDaYW8MGRI/AAAAAAAAAEo/GTXPBkq7oqw/s1600-h/controller_calib.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 173px;" src="http://4.bp.blogspot.com/_Fmx3P9hQJpA/SvDaYW8MGRI/AAAAAAAAAEo/GTXPBkq7oqw/s320/controller_calib.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5400056065226971410" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Once you've got all that installed and configured you can fire up Cortex Command, choose the Options submenu from the Main menu and you'll see the options menus as show below.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_Fmx3P9hQJpA/SvDatiuECYI/AAAAAAAAAEw/wyOn9qSXRZg/s1600-h/cc_options_screen.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 123px;" src="http://1.bp.blogspot.com/_Fmx3P9hQJpA/SvDatiuECYI/AAAAAAAAAEw/wyOn9qSXRZg/s320/cc_options_screen.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5400056429166201218" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From here use the left and right arrow buttons to select the Gamepad as the control scheme you'd like to use for your player and choose "configure". You'll then be presented with a screen to allow you to select the kind of controller you'd like configure.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_Fmx3P9hQJpA/SvDbROYiH5I/AAAAAAAAAE4/uT4kLkN_xAw/s1600-h/cc_dual_analog.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 151px;" src="http://1.bp.blogspot.com/_Fmx3P9hQJpA/SvDbROYiH5I/AAAAAAAAAE4/uT4kLkN_xAw/s320/cc_dual_analog.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5400057042182479762" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Choose the Dual Analog controller as this is what matches the Xbox 360 controller type. Once you've done that you can assign the different actions to the controller joysticks, buttons, triggers and menu buttons, as show below. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/SvDbtV3LSNI/AAAAAAAAAFA/AZd6qG1bBOs/s1600-h/cc_gamepad_config.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 153px;" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/SvDbtV3LSNI/AAAAAAAAAFA/AZd6qG1bBOs/s320/cc_gamepad_config.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5400057525226391762" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From there you can go back to the Main menu and fire up the game and play it with you controller. It's undoubtedly the best way! Enjoy!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_Fmx3P9hQJpA/SvDb9Cgvn4I/AAAAAAAAAFI/vEkNl_4GFPM/s1600-h/cc_title_screen.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 67px;" src="http://2.bp.blogspot.com/_Fmx3P9hQJpA/SvDb9Cgvn4I/AAAAAAAAAFI/vEkNl_4GFPM/s320/cc_title_screen.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5400057794909937538" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-5900235376619079036?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/5900235376619079036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2009/10/use-xbox-360-controller-with-cortex.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5900235376619079036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5900235376619079036'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2009/10/use-xbox-360-controller-with-cortex.html' title='Use a Xbox 360 Controller with Cortex Command on the Macintosh'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_Fmx3P9hQJpA/SvDZ9Z4ehlI/AAAAAAAAAEg/_HuPWDjXAQI/s72-c/controller_driver_dl.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-2908940759796095361</id><published>2009-10-22T20:17:00.000-07:00</published><updated>2009-10-22T05:17:41.896-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OSX'/><category scheme='http://www.blogger.com/atom/ns#' term='API'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='game development'/><category scheme='http://www.blogger.com/atom/ns#' term='Carbon'/><category scheme='http://www.blogger.com/atom/ns#' term='Eets'/><title type='text'>OSX: Carbon Event Loop not firing - Application unresponsive</title><content type='html'>In the development of Eets I've been using Apple's Carbon API. As some of my peers have correctly pointed out Carbon is slowly being deprecated, at least publically (outside of Apple). I'm pretty sure I've read somewhere that the Carbon API is still being heavy used to support the features underneath (for example in the Cocoa API). So this will likely be the last time I get to use it on any serious. I've already noticed that Googling for Carbon problems doesn't return a boatload of results. So I figure it's a pretty naive way of telling that Carbon it's really where the action is these days. &lt;br /&gt;&lt;br /&gt;I'm a little saddened by this. I think it's a well designed and useful API and I've found it quite enjoyable to use but it's clear that slowly C and C++ fall out of favour (yes, yes not without good reasons - I guess I'm just getting old and nostalgic). &lt;br /&gt;&lt;br /&gt;In case of the possibility there are some others out there still plugging away with Carbon or at least having a bit of a play, this post is for you! &lt;br /&gt;&lt;br /&gt;I had a particularly annoying problem the other night, and it stumped me for longer tham I'd like to admit. It was only some old crusty websites and a mailing list archive that gave me any clues as to what the problem might be. So for the sake of "paying it forward" I just thought I'd mention this problem I had and hope it might help somebody just like me. It was a very unintuitive problem. Most likely because I don't completely understand the way Carbon works with it's disk based resources. &lt;br /&gt;&lt;br /&gt;Eets, the title I'm working on, is basically a C++ and Carbon application. I am using CMake to generate the Xcode files. When the products are build, the .app directory and files are cobbled together mostly by hand (or by a script I wrote). I'd used interface builder to setup the basic window and toolbar settings. Somewhere along the line I'd obviously changed something outside of interface builder in the interface nib files. &lt;br /&gt;&lt;br /&gt;In my C++ code I've setup the basic Event loops, Events and Event Handlers. My problem began after adding some features and a compile. The main window would open but the whole application would just freeze. The menu wouldn't appear and the application window wouldn't respond to mouse clicks or drags. The window would just sit there and lose focus to any other window in it's way.&lt;br /&gt;&lt;br /&gt;I noticed this specifically happened once the code had started up and entered the  RunApplicationEventLoop.&lt;br /&gt;&lt;br /&gt;I kept thinking I'd setup the Event loop incorrectly or there was a bug in my code. I spent ages trying to work out what I could have done wrong. When I paused the application in the debugger the callstack looked like the one below.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;#0 0x900074c8 in mach_msg_trap ()&lt;br /&gt;#1 0x90007018 in mach_msg ()&lt;br /&gt;#2 0x90191708 in __CFRunLoopRun ()&lt;br /&gt;#3 0x90195e94 in CFRunLoopRunSpecific ()&lt;br /&gt;#4 0x927d5f88 in GetWindowList ()&lt;br /&gt;#5 0x927dc6f0 in GetMainEventQueue ()&lt;br /&gt;#6 0x927fe1c8 in GetApplicationTextEncoding ()&lt;br /&gt;#7 0x927fb698 in RunApplicationEventLoop ()&lt;br /&gt;#8 0x0000a264 in main (argc=2141449080, argv=0x38810040)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I eventually worked out what the problem was.  It turns out that&lt;br /&gt;RunApplicationEventLoop was freezing, and it was basically not handling events properly. This occurs when the CFBundleExecutable value in Info.plist file of the application bundle doesn't match the application name (set by "PRODUCT_NAME" in the build preferences of Xcode). Deep down within Carbon this apparently stops events from working. &lt;br /&gt;&lt;br /&gt;Annoyingly Eets, at the time, wasn't even being built as a bundle so I had to change that. It was time consuming and fiddly to do so - as CMake doesn't really have great support for Xcode application bundles, frameworks etc. It's getting there ... slowly.  &lt;br /&gt;&lt;br /&gt;After I changed CMake to create an application bundle and setup the Info.plist and .app directory structure, Eets is again working. I didn't change any of the C++ code to fix it. I just setup the .app as apparently required. Well I did learn something, even thought it wasted some time. &lt;br /&gt;&lt;br /&gt;I hope this is of use to some Carbon API users out there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-2908940759796095361?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/2908940759796095361/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2009/10/osx-carbon-event-loop-not-firing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/2908940759796095361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/2908940759796095361'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2009/10/osx-carbon-event-loop-not-firing.html' title='OSX: Carbon Event Loop not firing - Application unresponsive'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-4742605336531760064</id><published>2009-10-13T01:49:00.000-07:00</published><updated>2009-10-14T20:55:10.750-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='upcoming titles'/><category scheme='http://www.blogger.com/atom/ns#' term='Eets'/><title type='text'>Eets: Hunger. It's Emotional coming to Mac OSX</title><content type='html'>We hinted at the coming of Eets in an earlier development log post. Now we can tell you that Eets. Hunger. It's Emotional is on it's way to the Macintosh. We love this quirkly little platform puzzler and we hope that Macintosh owners will too.&lt;br /&gt;&lt;br /&gt;Eets was originally developed by &lt;a href="http://www.kleientertainment.com/"&gt;Klei Entertainment&lt;/a&gt; for the PC. Later in 2007, Klei developed Eets. Chowdown for the Xbox 360 LIVE Arcade which was well received. Klei have now moved on to some new and &lt;a href="http://kleientertainment.com/games/"&gt;exciting titles&lt;/a&gt; but it was their wish to see Eets come to the Macintosh. That's where we stepped in. We're now very excited to be part of bringing Eets to a new (and our adored) plaform.&lt;br /&gt;&lt;br /&gt;Eets has been described as a homage to some classic games of the past the likes of &lt;i&gt;Lemmings&lt;/i&gt; and &lt;i&gt;The Incredible Machine&lt;/i&gt;. With it's bright colours and eccentric cast of creatures you quickly find yourself endeared by this title. Players must navigate Eets to the end goal, a "puzzle piece", of each level by using a mix of beasties and contraptions with their own unique abilities and properties. Prankster Whales, Marshomechs, Chocolate Cannons and Radioactive Gingseng all play a part in solving the puzzles preventing Eets from getting where he's going. Food is greatly important to Eets and it directly affects his mood, thereby changing the way Eets will navigate his way through the level. We all agree, Eets is a very hungry animal - although it's not clear what kind of animal he is. At first sight it's not unreasonable to think of him as a dog, but I've seen him described as a tadpole with legs and teeth.&lt;br /&gt;&lt;br /&gt;Adding an extra dimension to the title is the inbuilt level builder allowing for user generated content. It adds hours of entertainment to Eets, when you've had your fill of playing through the levels shipped with the game.&lt;br /&gt;&lt;br /&gt;Bringing it to the Macintosh has been quite a challenge. It was engineered originally with little expectation of it ever coming to the Macintosh platform. Written directly on top of the Windows API and DirectX we've had to recode large parts of it to run it on the Macintosh; including a total rewrite of the graphics code to make use of Open GL. It's coming along nicely with the game almost playable (see very early development screenshot below).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://3.bp.blogspot.com/_Fmx3P9hQJpA/StaRN2AL3BI/AAAAAAAAAD8/zmdltyEiGfo/s1600-h/EetsMenu.png"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 230px; DISPLAY: block; HEIGHT: 157px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5392657270843366418" border="0" alt="" src="http://3.bp.blogspot.com/_Fmx3P9hQJpA/StaRN2AL3BI/AAAAAAAAAD8/zmdltyEiGfo/s200/EetsMenu.png" /&gt;&lt;/a&gt;&lt;br /&gt;The big things left remaining to address on the Macintosh version of Eets are sound and some control issues. We're pretty confident the majority of the really heavy lifting has been done and progress from this point on will be straight forward (touch wood).&lt;/p&gt;&lt;p&gt;We'll keep you posted on progress as we get closer to releasing this fantastic title for the Macintosh. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-4742605336531760064?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/4742605336531760064/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2009/10/eets-hunger-its-emotional-coming-to-mac.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/4742605336531760064'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/4742605336531760064'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2009/10/eets-hunger-its-emotional-coming-to-mac.html' title='Eets: Hunger. It&apos;s Emotional coming to Mac OSX'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_Fmx3P9hQJpA/StaRN2AL3BI/AAAAAAAAAD8/zmdltyEiGfo/s72-c/EetsMenu.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-2287165675851228092</id><published>2009-10-04T06:26:00.000-07:00</published><updated>2009-10-04T07:03:50.070-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delegates'/><category scheme='http://www.blogger.com/atom/ns#' term='Unity3D'/><category scheme='http://www.blogger.com/atom/ns#' term='game development'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Unity3D: Useful Tricks with Delegates</title><content type='html'>It's probably fair to say that Unity developers are quite a broad community skills wise. There is mix of first time game developers, seasoned professionals, programmer orientated folks and those of a more artistic nature. For me that's part of the beauty of Unity it has purpose at so many different levels.&lt;br /&gt;&lt;br /&gt;I wasn't that clear on a target audience for this post but I figure it's going to be of more use to the less experienced coders amongst us.&lt;br /&gt;&lt;br /&gt;As somewhat of an aside, I'd be curious to see the breakdown of Unity developers between those who exclusively use UnityScript (js) and those who predominantly use C#. I'm using a mix, initially I was sticking more with C#, since it's more similar to the language I know best which is C++. Now I find the terseness and succinctness of the UnityScript quite compelling and I've been using it a lot for the last few components I've work on. There's a downside to UnityScript for sure, but this isn't the topic I set out upon.&lt;br /&gt;&lt;br /&gt;One thing I kind of miss when using UnityScript in/as a behavior is the ability to create interfaces. When I say interfaces I mean in the object oriented sense. Interfaces are great when you want to interact with a whole bunch of different objects in the same way. To be more explicit lets look at it in the Unity context.&lt;br /&gt;&lt;br /&gt;So lets say I've got a GameObject which has an array of other game objects. (see screenshots). &lt;a href="http://4.bp.blogspot.com/_Fmx3P9hQJpA/SsimLT1UKjI/AAAAAAAAADU/15G95T_ggEI/s1600-h/master_exposed_vars.png"&gt;&lt;img style="MARGIN: 0px 0px 10px 10px; WIDTH: 200px; FLOAT: right; HEIGHT: 129px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5388739667381463602" border="0" alt="" src="http://4.bp.blogspot.com/_Fmx3P9hQJpA/SsimLT1UKjI/AAAAAAAAADU/15G95T_ggEI/s200/master_exposed_vars.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Normally these would be all identical objects, but what if we want to their functionality to vary somewhat from item to item? In object oriented languages this would be the realm of an interface, but in a Unity behavior (even thought it's an object oriented language) we don't directly have the capability of using an interface. So what can we do?&lt;br /&gt;&lt;br /&gt;We can use delegates. Delegates applied sparingly can somewhat mimic this nice object orientated characteristic. It's not quite as elegant but it works just fine.&lt;br /&gt;&lt;br /&gt;First of all, it's reasonable to ask if you've never come across the term. “What is a delegate?” It's called something slightly different depending on the computing language are talking about. In C and C++ the equivalent functionality you'd term a function pointer. In my mind the simplest description would be that a delegate is essentially a variable that contains a function or a method. You can “call” the variable just a like a function, and you can assign a function to the variable. If it doesn't make sense now, you may want to read a bit further to see it in action. This might make it clearer.&lt;br /&gt;&lt;br /&gt;Say for example we have a bunch of GameObjects. Sticking with some sort of familiar tradition lets call them widgets. So we've got a bunch of widget GameObjects, we've attached our widget script and they're all working nicely. Now if we'd like their behavior to vary a little, how are we going to do that?&lt;br /&gt;&lt;br /&gt;First of all lets define a widget script with a delegate that gets called in place of the normal functionality. Once we've done that we can attach another script to each widget to further refine it's behavior. The second script will attach to any selected widget GameObject and assign its own function to the delegate in the primary widget script. In this way you can modify the behavior of the original widget method however you wish. Let's look at some example code of this description, I'm of the opinion it will be much easier to understand.&lt;br /&gt;&lt;br /&gt;In my example I have a Master GameObject that contains an array of Widgets. The code of the example script is as such. Note the public array of widgets. This is exposed the inspector screen just as we like it. We assigned our selected widgets in the inspector (see screenshot).&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;/* Master.js */&lt;br /&gt;&lt;br /&gt;public var widgets : Widget[];&lt;br /&gt;&lt;br /&gt;function Update () {&lt;br /&gt;   for (var i = 0; widgets.Length; i++) {&lt;br /&gt;      widgets[i].DoSomething();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Next we create our Widget GameObjects and their associated widget script. &lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_Fmx3P9hQJpA/SsiqQAheicI/AAAAAAAAAD0/xpO1JWzxsB0/s1600-h/master_and_widget_scripts.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 200px; height: 65px;" src="http://1.bp.blogspot.com/_Fmx3P9hQJpA/SsiqQAheicI/AAAAAAAAAD0/xpO1JWzxsB0/s200/master_and_widget_scripts.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5388744146143840706" /&gt;&lt;/a&gt;&lt;br /&gt;The widget script is kind of like our object orientated interface through which our Master game object interacts with the widgets. As far as the Master GameObject is concerned, all the widgets are identical.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;/* Widget.js */&lt;br /&gt;&lt;br /&gt;private var doSomethingDelegate = null;&lt;br /&gt;&lt;br /&gt;function SetDoSomethingDelegate(func) {&lt;br /&gt;   doSomethingDelegate = func;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function DoSomething() {&lt;br /&gt;   if (doSomethingDelegate) {&lt;br /&gt;      doSomethingDelegate();&lt;br /&gt;   } else {&lt;br /&gt;   /*&lt;br /&gt;   Typical do something code ...&lt;br /&gt;   */&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function Update () {&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;For deviation of the widget behavior, let's look at the DoSomethingElse script, which will attach to a widget and this modify it's behavior when DoSomething is called. Note that the DoSomethingElse is assigned in this scripts Awake function. This assures it's ready to go when the action begins.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;/* DoSomethingElse.js */&lt;br /&gt;private var widget : Widget = null;&lt;br /&gt;&lt;br /&gt;function Awake() {&lt;br /&gt;   widget = GetComponent(Widget);&lt;br /&gt;   widget.SetDoSomethingDelegate(DoSomethingElse);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function DoSomethingElse() {&lt;br /&gt;   /*&lt;br /&gt;   The brand new wacky functionality that is different to the other widgets&lt;br /&gt;   */&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function Update () {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@script RequireComponent(Widget)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Finally note the “RequireComponent” directive to really make it clear that this script depends on the Widget script being in place.&lt;br /&gt;&lt;br /&gt;So as I hope you can see we can now modify a widget's behavior in a myriad of ways using this technique.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-2287165675851228092?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/2287165675851228092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2009/10/unity3d-useful-tricks-with-delegates.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/2287165675851228092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/2287165675851228092'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2009/10/unity3d-useful-tricks-with-delegates.html' title='Unity3D: Useful Tricks with Delegates'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Fmx3P9hQJpA/SsimLT1UKjI/AAAAAAAAADU/15G95T_ggEI/s72-c/master_exposed_vars.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-962223662651411057</id><published>2009-10-01T19:02:00.000-07:00</published><updated>2011-06-16T19:07:19.538-07:00</updated><title type='text'>Unity: Useful Tricks with Delegates</title><content type='html'>&lt;H2&gt;Post has moved - please click &lt;a href="http://divineabomination.blogspot.com/2009/10/unity3d-useful-tricks-with-delegates.html"&gt;here&lt;/a&gt;&lt;/H2&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-962223662651411057?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/962223662651411057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2009/10/unity-useful-tricks-with-delegates.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/962223662651411057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/962223662651411057'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2009/10/unity-useful-tricks-with-delegates.html' title='Unity: Useful Tricks with Delegates'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-4032759524086804518</id><published>2009-09-21T21:06:00.001-07:00</published><updated>2009-09-22T00:58:08.037-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cortex Command'/><category scheme='http://www.blogger.com/atom/ns#' term='Western Australia'/><category scheme='http://www.blogger.com/atom/ns#' term='game development'/><category scheme='http://www.blogger.com/atom/ns#' term='Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Eets'/><title type='text'>What's in the works</title><content type='html'>&lt;div&gt;As a recently formed independent games studio, we've been asked a number of times what our game plan is (pun intended). Starting the studio in Western Australia after working for some big name developers and publishers in Europe represents quite a change. Not only a simple change in geography but a huge change in proximity to the big market zeitgeist, talent pool and investment/funding opportunities.&lt;br /&gt;&lt;br /&gt;Despite having some experience in the industry to fall back on we're under no illusions as to what we can realisticaly achieve in a given timeframe. Not to mention we're all a bit older now than when we first entered the industry. No midnight crunches for us while trying to support families and preserve relationships. Initially we're going to keep things simple.&lt;br /&gt;&lt;br /&gt;For me that means the first and most import goal is publishing something. Set attainable goals and achieve them; get the dev cycles going and something on the table. Don't get me wrong, I want to create something special, but even Speilberg didn't create his finest films on his first foray out the door. So something special, but achievable.&lt;br /&gt;&lt;br /&gt;We were thinking about how this studio might work months before we left our industry jobs and made the migration to Australia. Looking around at opportunities to achieve our goals we did find a path that we think is a good place to start.&lt;br /&gt;&lt;br /&gt;It's always been my feeling that to create something worthwhile, it never hurts to understand what makes something worthwile. This thinking walks hand in hand with the ability to identify greatness in others or another's achievements. It was this thinking and a fortuitous meeting of minds with the developers from Data Realms that laid the path we would choose to take for an initial foray into Indie Game Development.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.datarealms.com/"&gt;Data Realms&lt;/a&gt; have spent years crafting a beautiful indie game known as &lt;a href="http://www.datarealms.com/games.php"&gt;Cortex Command&lt;/a&gt;. The first time I played it was a hurried affair in a lunch break. My initial exploration didn't do it justice but my interest was perked. A few weeks later with more time on my hands (and with a freshly downloaded build) I was able to spend enough time playing Cortex Command to begin to truely appreciate it. I felt then and still feel now that Cortex Command is one of those creative products that has some sort of destiny. With an idea in mind and a fanboy's appreciation in my heart, that motivated me to bring Cortex Command to the Macintosh. Spiritually, the Macintosh version of Cortex Command is the first title for Kruger Heavy Industries. The fact that it was mostly completed by myself before the company was formed probably only matters to the record keepers on Moby Games.&lt;br /&gt;&lt;br /&gt;Later in the piece we were very happy to have elected to be involved with Cortex Command. It did very well at the last Games Developers Conference 2009 in the Indie Games Festival, picking up two awards (&lt;a href="http://www.igf.com/2009finalistswinners.html"&gt;Technical Excellence&lt;/a&gt; and the &lt;a href="http://www.igf.com/2009finalistswinners.html"&gt;Audience Award&lt;/a&gt;) (some video coverage available &lt;a href="http://au.gamespot.com/xbox360/action/modernwarfare2/video/6206799"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_Fmx3P9hQJpA/SrhioO-j_TI/AAAAAAAAACM/kxNZyN-6xCw/s1600-h/ccfirstmacloadsm.jpg"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 200px; DISPLAY: block; HEIGHT: 152px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5384161797876219186" border="0" alt="" src="http://2.bp.blogspot.com/_Fmx3P9hQJpA/SrhioO-j_TI/AAAAAAAAACM/kxNZyN-6xCw/s200/ccfirstmacloadsm.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;Cortex Command is still actively in development, but is largely code complete - at least as far as the Macintosh porting effort is concerned. It's bugfixing and build making for the most part until release. A day we look forward to greatly. Dan, Prom and the rest from Data Realms are doing a fantastic job.&lt;br /&gt;&lt;br /&gt;So, what else is in the works for Kruger Heavy Industries? Fresh from our experience porting Cortex Command we picked up another great game we felt deserved some love on the Macintosh. Currently in active development is the Macintosh version of &lt;a href="http://www.eetsgame.com/"&gt;Eets: Hunger. It's Emotional&lt;/a&gt;. It was developed by our friends over at &lt;a href="http://kleientertainment.com/"&gt;Klei Entertainment&lt;/a&gt;. One of their first titles, it's been lavished with much love and attention to detail by the Klei team. We won't tell you too much about Eets right at this moment as we're looking forward to that in a future post. For now we would like you to know we're really looking forward to having Eets playable on the Macintosh and putting that second building block into the foundation of our little studio here in Western Australia.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-4032759524086804518?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/4032759524086804518/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2009/09/whats-in-works.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/4032759524086804518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/4032759524086804518'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2009/09/whats-in-works.html' title='What&apos;s in the works'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_Fmx3P9hQJpA/SrhioO-j_TI/AAAAAAAAACM/kxNZyN-6xCw/s72-c/ccfirstmacloadsm.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-9217108036931186435</id><published>2009-09-14T00:21:00.000-07:00</published><updated>2009-09-14T22:40:56.367-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Unity3D'/><category scheme='http://www.blogger.com/atom/ns#' term='game development'/><title type='text'>First Experiences with Unity 3D</title><content type='html'>&lt;a href="http://4.bp.blogspot.com/_Fmx3P9hQJpA/Sq8ovCd2E_I/AAAAAAAAACE/OEg9B816MTg/s1600-h/inspectorview.png"&gt;&lt;/a&gt; I first heard about Unity 3D early last year when some rumblings were made about it in Indie Games Circles. I wasn't really doing much with regards to Indie Games at the time and the company I was working for at time had it's own technology. On top of that Unity 3D was only really available for the Macintosh platform at the time (Windows version was still in Development). With all that in mind it didn't seem like I was going to get a chance to try out Unity 3D any time soon.&lt;br /&gt;&lt;br /&gt;Fast forward now to last month. I've just started a new contract for a local mob. We're using Unity 3D, predominately on the Windows platform. So I've finally got the chance to look at Unity 3D properly. My first impressions have been predominately positive.&lt;br /&gt;&lt;br /&gt;Unity is probably best described as a Game Engine and Editor “all in one”. It's an IDE, a level editor and properties tweaker. The professional version also has some source control functionality. There is a lot of functionality included in the package an it has the potential to save an enormous amount of development time.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The User Interface&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The User Interface is visually appealing, I suppose it would have to be to suit the fashion concious Macintosh crowd. The main interface is broken up in to several areas, the Game View, the Scene View, the Hierarchy View, an Assets View and the Inspector. The game view allows you to review the status of your Game, it's essentially what the game would like. It can be set to run, pause and stop basically allow you to run the game and see what's happening as you build it. If you want to see an animation running in your scene all you have to do is hit play.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;The scene view is similar to the Game view but is more orientated towards the actual development process. The scene view will show the scene and level objects in a simple form as well as many of the other implicit objects required for the game logic. The Camera in the scene view is free moving. Models and Game objects can be orientated, placed and scaled all the in the scene view. The interface is quite a lot like 3DS Max in the basic controls.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_Fmx3P9hQJpA/Sq8n7vipemI/AAAAAAAAAB8/42jlIrn9nP4/s1600-h/hierarchyview.png"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 205px; FLOAT: left; HEIGHT: 229px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5381563987058588258" border="0" alt="" src="http://1.bp.blogspot.com/_Fmx3P9hQJpA/Sq8n7vipemI/AAAAAAAAAB8/42jlIrn9nP4/s320/hierarchyview.png" /&gt;&lt;/a&gt; The hierarchy view (a panel really) is clearly inspired by a Scene Graph. It is essentially a list of objects in the scene, it also displays (via it's heirarchical nature) how these scene objects relate to each other. With it you can quickly find any object in your scene. In the Hierarchy panel, you can select an object, then when you move your mouse pointer over the scene display, pressing “F” will focus the scene view on the select hierarchy object. This without a doubt saves a lot of time. The hierarchy view is also useful for attaching components (behavior modifiers, graphical sugar and script/logic) to your scene objects.&lt;br /&gt;&lt;br /&gt;The inspector panel works closely with the hierarchy and asset views. All objects, behaviors and such in your scene have properties associated with them. These properties are exposed by the inspector and can be directly manipulated. Running the game in real time and tweaking values in the inspector allows you to rapidly tune settings for a visual effect or game play behavior.&lt;br /&gt;Finally the last main view or panel is the Project or Asset panel. This is where you can see all the assets in the scene. It's also where you can import new assets into the scene and construct prefab objects (objects that can be used again and again). All assets that have been imported into the assets can be edited from their new locations. Changes are re-imported and applied almost instantly.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Programming&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The actual programming side of is done via scripts written in Javascript or C# . Although there is the ability to use plugins in the professional version which are written in C, C++ and or C# - I assume on the Macintosh version we can also use Objective C). The Javascript is really UnityScript I suppose, while sharing many similarities with Javascript there are some notable differences as well, particularly when it comes to the way objects work.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;Scripts are typically assigned to game objects where their interfaces are called as the game logic progresses. Scripts assigned to game objects are known as behaviors. The script editor built into Unity 3D is Scite which is a well known simple editor. For more professional programmers who are used to the fully feature code environments such as the likes of Microsoft Visual Studio they may be disappointed. The environment notably lacks any easily accessible debugging, so you'll probably be spending a lot of time doing the old print debugging thing of yesteryear. Thankfully as everything else about the environment makes achieving results easy, this probably isn't as painful as it sounds. At least for small projects.&lt;br /&gt;&lt;br /&gt;Under the hood Unity basically creates dynamic libraries with the code that is compiled from the Game scene in development. This is most likely how the Unityscript/Javascript is so fast. Indeed the it becomes apparent that the Javascript i really just a thin veneer over the C# innards and as you start to realise the Unityscript's differences to Javascript it becomes clearer what is going on underneath. Of course it's not Microsoft .Net implementation but rather the C# implementation made available via the Mono project.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Source Control&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;In the professional version, Unity's own source control functionality is available. It's not brilliant. It's some hodgepodge or Unity 3D UI, with a backend of a Postgres database. Over low latency links it's horrible and generally it lacks features. Strangely it's also one of the most expensive accessories for Unity. I can sort of the see the logic in it, those requiring source control will most likely be the ones cashed up enough to be able to afford it. In effect subsidising the cost of Unity's development and cheap price to Indie Developers and students.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I'm overall feeling positive towards Unity 3D. I've still got a lot to learn but I can see enormous utility in the package for what amounts to (especially for Indies) a lot of bang for you buck. Depending on how my experiences go I may consider using the Engine/Tool myself on a title I've been mooting. I hope to post updates on my experiences as I go.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-9217108036931186435?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/9217108036931186435/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2009/09/first-experiences-with-unity-3d.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/9217108036931186435'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/9217108036931186435'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2009/09/first-experiences-with-unity-3d.html' title='First Experiences with Unity 3D'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_Fmx3P9hQJpA/Sq8n7vipemI/AAAAAAAAAB8/42jlIrn9nP4/s72-c/hierarchyview.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-5032420496348442550</id><published>2009-09-02T03:58:00.000-07:00</published><updated>2009-09-02T04:12:37.667-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='voip'/><category scheme='http://www.blogger.com/atom/ns#' term='business phone'/><category scheme='http://www.blogger.com/atom/ns#' term='net2max'/><title type='text'>Net2Max is in my good books</title><content type='html'>I've been using Net2Max for a couple of months now and I've been pretty happy with it. It's not exactly user friendly but once you understand the basics it does the job better and cheaper than everything else I've tried.&lt;br /&gt;&lt;br /&gt;My business number runs on the system. I just chose the country and state I wanted the number to be associated with and connected it to my Net2Max and account and voila - I've got a business number. I've connected this number to a PABX system that I configured on Net2Max to do call routing exactly how I want. For the most part it goes to my voicemail box. Messages that are left get emailed to me immediately, and since I'm almost always online I can check them immediately.&lt;br /&gt;&lt;br /&gt;If my business ever wants to expand or have a presence in another state or country, I can easily select a local presence number in just about every significant country. All the calls get routed back to my account.&lt;br /&gt;&lt;br /&gt;Alternatively I can can configure any voip phone to receive calls for this number, of my skype account if I so wish. It's extremely versatile. I've got a Belkin VOIP router at home, I've got four standard phone ports in the back. One port is configured for my home phone number, the 2nd port is configured to my business number. During the evening, I plugin my wireless handset into port 1. During the day, if I'm working from my home office, I plug the handset into port 2 and switch off the voicemail.&lt;br /&gt;&lt;br /&gt;All that flexibility is very useful and it comes at a reasonable price too. I'm currently spending about $3.00 Australian a month on business calls, the business number rental, voicemail and the pabx. I don't know how they do it so cheap. Best of all I think is the complete control I have over everything.  I don't have to call up some dope on the phone and ask them to change the configuration of anything, it's all handled through a website online that I can login to from anywhere.&lt;br /&gt;&lt;br /&gt;For me calling up is one of the last things I like to do, so this a huge plus to me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-5032420496348442550?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/5032420496348442550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2009/09/net2max-is-in-my-good-books.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5032420496348442550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5032420496348442550'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2009/09/net2max-is-in-my-good-books.html' title='Net2Max is in my good books'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8309530329868152793.post-5150807214047607456</id><published>2009-05-05T01:23:00.000-07:00</published><updated>2009-09-21T22:12:49.373-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Welcome'/><category scheme='http://www.blogger.com/atom/ns#' term='Introduction'/><title type='text'>Welcome</title><content type='html'>Well a  warm hello. This is the start of our development blog. Lets see how we go. We'll be blogging about technical things, the studio and other interesting things related to games development and Indie Games.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8309530329868152793-5150807214047607456?l=divineabomination.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://divineabomination.blogspot.com/feeds/5150807214047607456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://divineabomination.blogspot.com/2009/05/welcome.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5150807214047607456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8309530329868152793/posts/default/5150807214047607456'/><link rel='alternate' type='text/html' href='http://divineabomination.blogspot.com/2009/05/welcome.html' title='Welcome'/><author><name>montdidier</name><uri>http://www.blogger.com/profile/08582510323638869405</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/_Fmx3P9hQJpA/Srhj2Nl4TCI/AAAAAAAAACY/PgzgYvDa7o0/S220/montdidier3.jpg'/></author><thr:total>0</thr:total></entry></feed>
