<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Cocoadex</title>
    <link rel="alternate" type="text/html" href="http://cocoadex.com/" />
    <link rel="self" type="application/atom+xml" href="http://cocoadex.com/atom.xml" />
    <id>tag:cocoadex.com,2007-11-12://4</id>
    <updated>2008-07-30T00:23:11Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Personal 4.12</generator>

<entry>
    <title>How I got started programming</title>
    <link rel="alternate" type="text/html" href="http://cocoadex.com/2008/07/how-i-got-started-programming.html" />
    <id>tag:cocoadex.com,2008://4.15</id>

    <published>2008-07-30T00:23:11Z</published>
    <updated>2008-07-30T00:23:11Z</updated>

    <summary>Known for my promptness, it is no surprise that I&apos;ve taken approximately 28 days to reply to the indubitable Anne K. Halsall&apos;s tagging of myself and several esteemed others to give the wonderful world of the internet my story (of...</summary>
    <author>
        <name>Elliott</name>
        
    </author>
    
    <category term="me" label="Me" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://cocoadex.com/">
        <![CDATA[<p>Known for my promptness, it is no surprise that I've taken approximately 28 days to reply to the indubitable <a href="http://www.randomnonsequitur.com">Anne K. Halsall</a>'s <a href="http://www.randomnonsequitur.com/post/32">tagging</a> of myself and several esteemed others to give the wonderful world of the internet my story (of all people!). Not only that, but to be listed with the people she listed me with! I can cross off "Appear in a list with <a href="http://borkwarellc.wordpress.com/2008/07/01/how-i-got-started-in-programming/">Mark Dalrymple</a> and <a href="http://www.possibleprobable.com/?p=60">Aaron Hillegass</a>" off my life's to-do list.</p>

<p>Without further ado, I present the story, as requested, many moons ago.</p>

<p><b>How old were you when you started programming?</b></p>

<p>Ah. This is an interesting question. Normally here, you'd get a fantastically woven tale of discovering a UNIX machine deep within the bowels of your college, and plugging away for hours and hours learning as much as possible, or even having an Apple ][ as a child, and pecking away at sweet BASIC programs.</p>

<p>I did not do this. Not at all.</p>

<p>I started programming when I was 17.</p>

<b>The Setup.</b>

<p>Most of my pre-programming life was spent enjoying other people's hard work -- I played video games. A lot of video games. I played a bit of baseball growing up, but by the time third grade rolled around, I had two loves in my life: Playing Oregon Trail in Typing class, and music.</p>

<p>My father was a trumpet player in his younger days, and coincidentally, also one of the first computer programmers at his <a href="http://www.lsu.edu">university</a>. Despite being a architecture major, he loved computers and got involved with them as much as he could. When I came to live with my father in Texas when I was 8, he began influencing my childhood with his love of computers, and I was hooked. My dad and I bonded over computers, and he taught me everything I could possibly absorb.</p>

<p>Back then, we were Microsoft men. We anticipated the release of new versions of Windows and Office with great anticipation, so that we could pick them apart and learn everything about them. We got the internet in 1994 or so, good old AOL. We jumped ship to cable internet as soon as it was possibly available, learning about ethernet and Windows networking (ugh), and everything as we went.</p>

<p>However, I really knew nothing about software. In fact, I knew more about interrupts, device communication, and USB long before I ever understood what a pointer was. As I grew up, I cared less and less about about what came out of Redmond, and more and more about what my computer could actually <em>do.</em> I embraced software in the form of computer games, eventually playing at a pretty high level in a couple of my favorites (competitive gaming, ugh). I was also into music a lot, playing trumpet, baritone/euphonium, tuba, and finally trombone throughout my childhood and into high school. I played with various pieces of musical software in my later years: Reason and Fruity Loops mostly, and somewhat enjoyed that.</p>

<p>By my senior year, I was pretty sure I'd be majoring in music, Trombone Performance I believe, and that computers were just a hobby.</p>

<b>How I got started programming (and changed my complete life plan)</b>

<p>Two things, or maybe, more specifically, two people completely destroyed that idea.</p>

<p>A good amount of my time was spent playing text based games oddly enough. My friends and I were into <a href="http://en.wikipedia.org/wiki/MUDs">MUDs</a> big time, which was rather odd in a time where Everquest was insanely popular. One friend, in particular, really liked MUDs, enough to learn how they work, and began work on one himself. At some point, I joined the fray. I had a bit of experience working on a MUD we all played, doing text-based level design. It was rather basic, but involved a lot of writing, and I enjoyed it a lot. So, I went about sitting next to him, writing room after room after room. Every now and then, I looked over and saw it - a stark black background with bright glowing white letters, arranged haphazardly in weird patterns on his screen. It was code.</p>

<p>My quick looks slowly became long stares, and as I saw what he was doing, and what it became, I was blown away. I guess I had never really though about software, and how it was made. I recalled back to my excitement over software releases, and realized how much excitement throughout my entire life was completely based on software. This was awesome, and I wanted to be able to do it. The next day, I went to the local Borders and picked up my very first programming book: <a href="http://oreilly.com/catalog/9780596004194/?CMP=AFC-ak_book&ATT=Practical+C%20%20+Programming">Practical Programming in C++</a>. I read the book every day. I ended up reading it around five times before I graduated high school. I loved it so much, I ended up taking a computer science class my senior year, which was a joke at that time. I excelled, helped other people understand, and loved every second of it. I had only ever been really good at one other thing: music, and it was awesome to have something else to join the party. Little did I know, I was a terrible programmer, but no matter, it was an amazing feeling.</p>

<b>No, there is another...</b>

<p>I love skateboarding video games. I mean really love them. I absolutely adored Tony Hawk's Pro Skater, and pretty much everything about the series of games.</p>

<p>A friend of many of my friends, let's call him Andy, since that's his name, played this game at an insane level. I never knew this mind you, all I knew is that one day, I heard that Andy played Tony Hawk so well, that <a href="http://neversoft.com/">Neversoft</a> wanted to hire him to test Tony Hawk. This was it. At this point, I realized that video games were a major industry, and that computer software of all kinds, was an even bigger industry. It all brought me to the realization that music needed to be the hobby, and that I needed to make software for a living. After some careful thought, I realized that this plan was much more feasible than using money made from music to fund my software plans. I graduated high school, and enrolled in college as a computer science major.</p>

<p>Coincidentally, Andy was on stage during the premiere of <a href="http://www.youtube.com/watch?v=FtdGJx3A14w">Guitar Hero World Tour</a>, playing drums, which caused me to freak out. He's now a designer at Neversoft, and I <strong>LOVE</strong> Guitar Hero.</p>

<b>What was your first language?</b>

<p>I guess C++, which is really quite bad. Never ever use C++ as the language you learn programming with, it's awful. When I graduated, I got a Powerbook G4, much to the bickering of my father, who wanted me to get a Dell or something, but I knew what I was doing. :)</p>

<p>That was the first machine I owned that I ever programmed on, and I refused to write a line of C++ on it. I bought Cocoa book after Cooca book, taught myself Objective-C with the help of Steven Kochan, and Cocoa with the help of Aaron Hillegass, and never looked back.</p>

<b>What was the first real program you wrote?</b>

<p>Jeez, this is a hard one to answer.</p>

<p>There were tons of little one-offs, and the projects from Aaron's book, not to mention five years of CS assignments. Adium is the first I ever shipped any code, so I'll say it was that, though of course, I didn't write all of that.</p>

<p>The first thing I actually wrote and finished all by myself and could be called a real program was actually Photo Touch. All the <em>real</em> experience I had up until then had been on teams, because I love working on teams of amazing people.</p>

<b>What languages have you used since then?</b>

<p>Well, Objective-C primarily. However, I've dabbled in all kinds of stuff: C, [C++], Java, Javascript, Python, Ruby, and Prolog.</p>

<b>What was your first professional programming gig?</b>

<p>This is a hard one to answer.</p>

<p>In November of 2006, I decided I wanted to work on an open source project, in what I will call the best decision I've ever made in my life. I chose <a href="http://www.adiumx.com">Adium</a>, and was asked to join the development team in December of the same year. Despite the fact that since that initial flurry of activity, I haven't gotten to work on it nearly enough due to the insanity stemming from my association with the project, leading to my actual first professional programming gig. I hold Adium in high regard, and will never forget the impact it's had so far.</p>

<p>I accepted my first professional gig in May of 2007, as an intern at <a href="http://www.apple.com">a little fruit company</a>, who's work I'm quite partial about. I worked on a pretty secret project, that would eventually become <a href="http://www.apple.com/logicstudio/mainstage/">MainStage</a>. I had the incredible luck to land my dream job of working on the Audio/Music team at said fruit company, which had been my dream since getting my first Mac out of high school, which came with <a href="http://www.apple.com/ilife/garageband/">Garageband</a> 1.0, which I loved to death.</p>

<b>If there is one thing you learned along the way that you would tell new developers, what would it be?</b>

<p><strong>NETWORK.</strong> I try to kid myself that I got really really lucky, but ultimately, my networking decisions (combined with a ton of luck, seriously) are what got me where I am. Take the time to get to know people, I am still around 9,999,999 beers in debt to <a href="http://iamthewalr.us/">Colin Barrett</a> at this point.</p>

<p>Find smart people. Surround yourself with them. Most importantly, show off anything you think is cool. Everyone loves something cool. Not only will you inspire yourself to keep doing what you do, but you'll inspire hundreds, if not thousands of others, to keep at it as well.</p>

<b>What's the most fun you've had programming [that I can talk about]?</b>

<p>A tough one! ;)</p>

<p>I quite enjoyed writing Photo Touch, and showing it to my fellow students at school. Despite it being rather simple, I had a gigantic group of younger students surrounding me asking me questions about it, Mac programming, and working for fruit companies.</p>

<p>It was a real turning point, that let me know I was on the right track, and vindication about your life choices is extremely important.</p>

<b>Corollary: Why aren't you writing video games?</b>

<p>Great question!</p>

<p>I got into application development for some unknown, odd reason. I realized that applications make the world go round. Every day, we use a multitude of applications to make our lives work the way they do, and that writing these applications posed a unique challenge: How do you write something that someone <strong>wants</strong> to use every day of their life?</p>

<p>I'm still not really sure, although I suspect that I'm at the right <a href="http://www.apple.com">place</a> to find out, all things considered.</p>

<p>I imagine someday, I may make a foray into game programming. I've certainly given it some thought lately, but my love for user interfaces is what keeps me here, and doing what I do, and hopefully making apps that people use every day of their lives.</p>

<p>Thanks to <a href="http://www.randomnonsequitur.com">Anne</a>, <a href="http://iamthewalr.us/">Colin</a>, <a href="http://www.kochan-wood.com/">Steve Kochan</a>, <a href="http://www.possibleprobable.com/">Aaron Hillegass</a>, <a href="http://borkware.com/">Mark Dalrymple</a>, and well, pretty much everyone involved. </p>


]]>
        
    </content>
</entry>

<entry>
    <title>Natural User Interface Group</title>
    <link rel="alternate" type="text/html" href="http://cocoadex.com/2008/04/natural-user-interface-group.html" />
    <id>tag:cocoadex.com,2008://4.14</id>

    <published>2008-04-01T23:58:32Z</published>
    <updated>2008-04-01T23:58:32Z</updated>

    <summary> Recently, as you may have noticed, I&apos;ve gotten into working with multi-touch a lot. It&apos;s a common focus among modern HCI experts, and as many people would agree, it seems to be the direction we are heading in the...</summary>
    <author>
        <name>Elliott</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://cocoadex.com/">
        <![CDATA[<p />

Recently, as you may have noticed, I've gotten into working with multi-touch a lot. It's a common focus among modern HCI experts, and as many people would agree, it seems to be the direction we are heading in the field. While some would argue that the technology is far from mainstream, one group in particular is working towards fixing that in the best kind of way -- open source.

<p />

The <a href="http://www.nuigroup.com">Natural User Interface Group</a> is a group of like-minded individuals working towards making multi-touch surfaces more mainstream. They've got a lot of open source software and step-by-step guides to making multi-touch surfaces, and getting software up and running with them. In addition, they've got a great IRC channel on freenode, #nuigroup where a lot of friendly and helpful people hang out answering questions and talking multi-touch. I stopped by after getting an comment on Photo Touch from one of their members, and ended up staying way later than I should have discussing multi-touch. 

<p />

In addition, NUIG is a <a href="http://code.google.com/soc/2008/">Google Summer of Code</a> group this year, so I encourage anyone still looking for a group to submit an application to, to definitely check them out. One individual, who has been working on NUIG related things with regards to Cocoa is <a href="http://multitouch.fieryferret.com/">Bridger Maxwell</a>. He and I talked at length about some more in depth multi-touch capabilities coming to Cocoa as apart of his proposal to the NUIG for this year's summer of code. Hopefully, he'll get accepted, and he and I can work together to bring some better support for Mac OS X, Cocoa specifically, in the open source multi-touch world. Like Bridger says on his blog, Cocoa provides a lot of great tools for data visualization and allows developers to create amazing looking graphics code with a fraction of the code of other platforms.

<p />

If you are interested in multi-touch, and the possibilities that are out there, you should definitely check this out. If <a href="http://www.appleinsider.com/articles/08/04/01/apple_developing_full_multi_touch_macs_report.html">these</a> rumors are to be believed, we might all be writing multi-touch code much sooner than we think.

<p />

]]>
        
    </content>
</entry>

<entry>
    <title>That&apos;s rich.</title>
    <link rel="alternate" type="text/html" href="http://cocoadex.com/2008/04/thats-rich.html" />
    <id>tag:cocoadex.com,2008://4.13</id>

    <published>2008-04-01T22:53:42Z</published>
    <updated>2008-04-01T22:53:42Z</updated>

    <summary>FCC to turn down Skype&apos;s mobile open access plea: &quot;The FCC plans to dismiss a request from Skype that would require mobile operators to open their networks. Skype? Wanting someone to be more open? Are you serious? Get back to...</summary>
    <author>
        <name>Elliott</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://cocoadex.com/">
        <![CDATA[<p><a href="http://rss.macworld.com/~r/macworld/feeds/main/~3/262232563/skype.html">FCC to turn down Skype's mobile open access plea</a>: "The FCC plans to dismiss a request from Skype that would require mobile operators to open their networks.
<p><a href="http://rss.macworld.com/~a/macworld/feeds/main?a=t057bE"><img src="http://rss.macworld.com/~a/macworld/feeds/main?i=t057bE" border="0"></img></a></p>

<p>Skype? Wanting someone to be more open? Are you serious? Get back to me when you open your own software up to third parties, then you can go back to writing petitions for other people to open up their own.</p>

<p>(Via <a href="http://www.macworld.com">Macworld</a>.)</p>]]>
        
    </content>
</entry>

<entry>
    <title>&quot;Custom&quot; Multi-touch Gestures with MultiClutch and Safari/WebKit</title>
    <link rel="alternate" type="text/html" href="http://cocoadex.com/2008/03/custom-multitouch-gestures-wit.html" />
    <id>tag:cocoadex.com,2008://4.12</id>

    <published>2008-04-01T01:39:54Z</published>
    <updated>2008-04-01T01:39:54Z</updated>

    <summary>Back again? So soon you say? Of course! MultiClutch is a great program by Will Henderson which allows you to assign a keyboard shortcut to be executed when you perform a gesture on the trackpad. This proves immensely useful for...</summary>
    <author>
        <name>Elliott</name>
        
    </author>
    
        <category term="Cocoa" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://cocoadex.com/">
        <![CDATA[Back again? So soon you say? Of course!
<p />
<p><a href="http://wcrawford.org/2008/02/28/everytime-i-think-about-you-i-touch-my-cell/">MultiClutch</a> is a great program by Will Henderson which allows you to assign a keyboard shortcut to be executed when you perform a gesture on the trackpad. This proves immensely useful for providing improved gesture functionality to applications.</p>

<p>It should come to no surprise to you dear reader, that the initial functions for the gestures currently in Leopard slightly...well, dissatisfy me. I'm of the opinion that multitouch should be more than just bindings for keyboard shortcuts, but since I have no control over that, I'd at least like the shortcuts to be <em>useful</em> ones. So, with that in mind, I offer up my highly improved (in my own opinion of course) bindings for WebKit/Safari (They will work for both, but you have to bind them for both.)</p>

<div style="text-align:center;"><img src="http://cocoadex.com/images/webkit-prefs.png" alt="webkit-prefs.png" border="0" width="439" height="275" /></div><image-goes-here>

<p />

<p>Let me translate for you dear reader.</p>

<p>Zoom In is the pinch gesture, and it closes the current tab, or window if there is only one tab. This is the only <em>dangerous</em> one, since it's pretty easy to do the pinch gesture when you are scrolling. This can cause some faulty tab closures, which is annoying, and I'm habituated to hitting Cmd+W, but sometimes when I click and link and get a new window, it's really nice to be able to pinch it away.</p>

<p>Zoom Out is the zoom/expand gesture, and it opens a new tab. I use this ALL THE TIME, and really think it should be the Safari default instead of text size, but hey, what do I know?</p>

<p>Swipe Up and Swipe Down go Forward and Backward respectively. I liked these at Left/Right, but not as much as I like changing tabs (What Swipe Left and Swipe Right are bound to) with left and right, and I do that a lot. I understand that the gesture mimics the buttons, but again, I think Forward (Up) and Back (Down) make more spatial sense.</p>

<p>Finally, my favorites. Rotate Right is Cmd+R, which is Refresh. I maintain that I came up with this independently of <a href="http://waffle.wootest.net/2008/03/14/slowly-disengage-the-clutch/">Jesper</a>, but whatever. It's awesome, and every app that has refresh should use it.</p>

<p>And now, the trump card. Safari 3 added a menu option called "Merge All Windows" which merges every open window and all their tabs into a single window. Similar to above, sometimes I use those pop-up'd windows to continue my browsing, which means I get several windows with several tabs each. This is annoying, and happens frequently enough. However, this has no keyboard shortcut! So sad.</p>

<p>Mac OS X makes this easy however, using "Keyboard Shortcuts" under Mouse/Keyboard Preferences.</p>

<div style="text-align:center;"><img src="http://cocoadex.com/images/mouse-prefs.png" alt="mouse-prefs.png" border="0" width="421" height="38" /></div>

<p />

<p>You can see that I've added a keyboard shortcut "Cmd+Shift+M" to merge all windows to Safari. NOTE TO WEBKIT USERS: IF YOU USE WEBKIT NIGHTLIES IT STILL GOES UNDER SAFARI. THAT IS ALL. After I've done this, I can easily bind a MultiClutch gesture to do this, and that's just what I did.</p>

<p>So that does it. Let me know what you think in the comments, or on Twitter or something. Also, let me know what other bindings you have for applications.</p>

<p>BONUS: Adium implements gestures in 1.3. They are awesome! Thanks to Zac West for them.</p> 

]]>
        
    </content>
</entry>

<entry>
    <title>Photo Touch</title>
    <link rel="alternate" type="text/html" href="http://cocoadex.com/2008/03/photo-touch.html" />
    <id>tag:cocoadex.com,2008://4.11</id>

    <published>2008-03-30T23:36:45Z</published>
    <updated>2008-03-30T23:36:45Z</updated>

    <summary>Long time no see blog! However, I&apos;ve been busy. Today, I&apos;d like to show everyone one of my final projects for school, which happens to be a multi-touch demonstration using my new Macbook Air (awesome) and Core Animation (also awesome)....</summary>
    <author>
        <name>Elliott</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://cocoadex.com/">
        <![CDATA[<p>Long time no see blog!</p>

<p>However, I've been busy. Today, I'd like to show everyone one of my final projects for school, which happens to be a multi-touch demonstration using my new Macbook Air (awesome) and Core Animation (also awesome). It's called Photo Touch, and I'll go ahead and let the video do the talking.</p>

<p><object width="425" height="350"> <param name="movie" value="http://www.youtube.com/v/D7x7jV3P1-0"> </param> <embed src="http://www.youtube.com/v/D7x7jV3P1-0" type="application/x-shockwave-flash" width="425" height="350"> </embed> </object></p>

<p />


<p>Hope you enjoyed that. I'll be back with more real soon. Like I said in the video, hopefully the code will be available after the presentation on the 11th of April. Wish me luck!</p>

<p>Thanks again to <a href="http://www.patrickgibsonphotography.com">Patrick Gibson</a>, <a href="http://cs.nyu.edu/~jhan/">Jefferson Han</a>, and <a href="http://www.theocacao.com">Scott Stevenson</a> for their contributions to Photo Touch. (Photos, Ideas, and NanoLife Random Path code respectively).</p>]]>
        
    </content>
</entry>

<entry>
    <title>Macbook Air vs. iPhone: A Multi-touch Mystery</title>
    <link rel="alternate" type="text/html" href="http://cocoadex.com/2008/02/macbook-air-vs-iphone-a-multit.html" />
    <id>tag:cocoadex.com,2008://4.10</id>

    <published>2008-02-04T21:57:28Z</published>
    <updated>2008-02-04T21:57:28Z</updated>

    <summary>Continuing my theme of Macbook Air trackpad related posts, today we&apos;re going to look at some intriguing differences in behavior between the trackpad and the device that made multi-touch all the rage -- the iPhone. The particular behavior I&apos;m talking...</summary>
    <author>
        <name>Elliott</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://cocoadex.com/">
        <![CDATA[<p>Continuing my theme of Macbook Air trackpad related posts, today we're going to look at some intriguing differences in behavior between the trackpad and the device that made multi-touch all the rage -- the iPhone. The particular behavior I'm talking about is the swipe behavior in Preview.app. The behavior in Preview is obviously an attempt to mimic how the iPhone allows one to browse through all of the open documents in Preview. In this example we'll use a group of photos to exhibit both behaviors.</p>

<p>Let's start with the iPhone.</p>
<p>On the iPhone, the idea is that the user is reaching out and touching the photo, and "flicking" it to the left or right. So, let's say you reach out to the right side of a photo, and slide your finger to the left. The image then follows your finger, sliding off to the left, and the next image slides in from the right. This is pretty expected -- you have flicked the photo off the screen to the left, and it follows your finger off the edge of the screen. Even if you reach out and touch the middle of the photo and flick just a little bit to the left, the same expected behavior happens. You've grabbed the photo, pushed/flicked it off to the left, and a new image comes in from the right. Of course, the images aren't unlimited and if you attempt to do this when there is not a next image the image attempts to move off to the left, and then bounces back to show you that no image to the right exists, and that you are at the end. This all makes perfect sense, is pretty intuitive, and seems like the logical behavior to model the swipe behavior in Preview after, right?</p>

<p>Apparently not.</p>

<p>As an iPhone user, I approached the Macbook Air with a great bit of excitement. While the applications that currently support gestures don't exactly make me jump for joy, the potential for these gestures in third party applications is simply put, awesome. However, I'd at least expect <em>some</em> consistency between the two platforms.</p>

<p>Unfortunately, Preview falls short.</p>

<p>In Preview, swipes aren't as sophisticated, and in my opinion, not as well thought out as on the iPhone. Instead of the reaching out, touching, and flicking metaphors that work so well on the iPhone, swipes on the Macbook Air's trackpad simply move in the direction of the swipe rather uninterestingly. Sure, they animate nicely, taking full advantage of Core Animation, and when they reach the end of the set the image bounces back. However, Preview decides that reality, and thus platform parity, should fly out the window.</p>

<p>A swipe to the right in Preview, moves to the photo to the right. A swipe to the left in Preview, moves to the photo to the left. This is the opposite behavior you'd expect if you've ever used an iPhone, and sure enough, the opposite behavior I think you'd actually want. Using a multi-touch trackpad is not analogous to using the arrow keys. I'm not trying to arrow through my pictures, my mind is expecting a higher level experience -- I am reaching out and literally swiping through my photos, just like I might turn the pages of a book. Similarly if I rotate, or magnify my pictures, I'd be expecting the computer to act like I'm picking up a photo, and pulling the photo closer to me respectively, and indeed this is what happens. </p>

<p>Now then, it's possible that this functionality is actually intended. If we look at another application that implements multi-touch capability, the current behavior is actually correct. In Safari, moving to the right should in fact send us forward, and moving to the left, should send us backwards. That makes sense after using it a couple of times. There are thus two arguments that can be leveraged for the case of Preview's behavior. The first is system parity. Other applications act this way, thus, Preview should as well. I'm guessing that's the one they chose, and that's why it's implemented this way. I argue that is should be changed, because it just feels wrong. Even more so after you've used an iPhone for about two minutes. The second reason, is that Preview is not necessarily running a full screen context. Thus, the idea of flicking pictures isn't especially clear. However, I get the feeling that's exactly what they <em>were</em> attempting to mimic. When you reach the end of a set of photos, the image has a nice bounce effect, just like on the iPhone. However <em>it bounces the wrong way!</em> That's right, when you get to the end of a group of photos, and continue to scroll as if another photo should be there, the image slides to the <em>right</em> and then bounces back. This is completely <strong>wrong.</strong> Since the photo should be sliding off to the left, it should do so, and then bounce back, very similarly to how the iPhone works.</p>

<p>I think this ultimately shows one of the interesting aspects of these trackpads being integrated into our computers. It's very easy to get confused about how they should work. Multi-touch <em>shouldn't</em> be just an alternative way to arrow through things. It's an advanced and sophisticated input method, and requires programmers to really think about how users are going to interact with their computer when using gestures. Assuming Apple continues to integrate this technology into their laptops, we will soon be at a point where multi-touch is a big deal. Both platform parity and system parity need to be considered, but more importantly a great deal of thought needs to go into this process, and whether through guidance from the top as to how users should be expected to interact with the multi-touch trackpad, or through a standards system of our own, right now it's up to the developers using the technology to shape the way users use this technology. </p>

<p>All in all, there are far more iPhones and iPod touches around than Macbook Airs. Far more people are going to be used to using these devices, rather than a Macbook Air, and thus I think it's clear the paradigms we should strive to mimic.</p>

<p><a href="http://boredzo.org/blog/">Peter Hosey</a> has pointed out, and I agree with him really, that Safari should mimic the iPhone behavior as well. After all, who doesn't want to flick through webpages?</p>

<p>Bugs have been filed on Preview and Safari: <a href="rdar://problem/5723575">here</a> and <a href="rdar://problem/5723608">here</a>.</p>

<p>Ciaó</p> 

<p><a href=http://www.cocoadex.com>⌘</a></p>]]>
        
    </content>
</entry>

<entry>
    <title>NSResponder Modifications: Swipe, Rotate, and Magnify</title>
    <link rel="alternate" type="text/html" href="http://cocoadex.com/2008/02/nsevent-modifications-swipe-ro.html" />
    <id>tag:cocoadex.com,2008://4.9</id>

    <published>2008-02-01T19:38:36Z</published>
    <updated>2008-02-02T00:17:45Z</updated>

    <summary>So, I&apos;m sure you&apos;ve heard of the Macbook Air and it&apos;s revolutionary multi-touch trackpad, borrowed from the iPhone technology. The basic gist of it is that it provides application specific gestures that can be triggered by performing some gestures on...</summary>
    <author>
        <name>Elliott</name>
        
    </author>
    
        <category term="Cocoa" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://cocoadex.com/">
        <![CDATA[So, I'm sure you've heard of the <a href="http://www.apple.com/macbookair">Macbook Air</a> and it's revolutionary multi-touch trackpad, borrowed from the iPhone technology. The basic gist of it is that it provides application specific gestures that can be triggered by performing some gestures on the new trackpad. With that in mind, every Cocoa developer should be asking themselves this question: What has Apple done to NSEvent [and friends] to facilitate gestures in their own applications and how can I do it in mine?<div><br class="webkit-block-placeholder" /></div><div>With the help of my local Apple Store's Macbook Air, and some NSEvent knowledge, I'm going to answer exactly that.</div><div><br /></div><div>Alright, since we're dealing with what are presumably new events, the first place we should check is the system version of NSEvent, hoping that maybe, just maybe Apple has defined them for us. Since this a blog post of decent length, you can infer what I did -- they aren't documented at all. Hooray.</div><div><br class="webkit-block-placeholder" /></div><div>This is furthermore supported by a small test application that I wrote which logs all of the events coming out of NSApplication by replacing my NSPrincipalClass key in Info.plist with the name of my subclass of NSApplication - GestureTest. By overriding <span class="Apple-style-span" style="font-style: italic;">-(void)sendEvent:(NSEvent *)anEvent, </span>and logging every event that comes out, I can get a quick overview of <span class="Apple-style-span" style="font-weight: bold;">every single event</span> that gets passed to my application. This is very handy in a lot of situations, particular this one. Upon closer inspection, we have five new events - three events for each gesture, and two events corresponding to the beginning and end of a gesture respectively.</div><div><br class="webkit-block-placeholder" /></div><div>The gestures are as follows, grouped with their corresponding NSEventType.</div><div><br class="webkit-block-placeholder" /></div>BeginGesture: 19 (I think, I forgot to double check this, woops!)<div>Swipe: 31</div><div>Magnify: 30</div><div>Rotate: 18</div><div>EndGesture: 20<br /><div><br class="webkit-block-placeholder" /></div><div>Since these events are standard NSEvents, they are affected by flag modifiers (i.e. we can differentiate between a swipe with Command held down and a swipe with Command-Option held down). </div><div><br class="webkit-block-placeholder" /></div><div>Thus, we have a basic way to check for these events -- we can check the flag and handle gestures appropriately. However, this is pretty inefficient - we have to check every event for this type and it isn't very flexible - we have to intercept at the NSApplication level. No good.</div><div><br /></div><div>If you recall from Chapter 16 of Aaron Hillegass' excellent book <a href="http://www.amazon.com/Cocoa-Programming-Mac-OS-2nd/dp/0321213149/ref=pd_bbs_1?ie=UTF8&amp;s=books&amp;qid=1201903960&amp;sr=8-1">Cocoa Programming for Mac OS X</a> (Preorder the third edition <a href="http://www.amazon.com/Cocoa-Programming-Mac-OS-3rd/dp/0321503619/ref=pd_bbs_2?ie=UTF8&amp;s=books&amp;qid=1201904079&amp;sr=8-2">here</a>), every object that is going to respond to events needs to descend from <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/Reference/Reference.html">NSResponder</a>. NSResponder implements the public interface for responding to various mouse and keyboard events - our good friends <span class="Apple-style-span" style="font-style: italic;">-(void)mouseDown:(NSEvent *)anEvent</span>, <span class="Apple-style-span" style="font-style: italic;">-(void)keyDown:(NSEvent *)anEvent</span>, and friends. However, this documentation hasn't been updated for the Macbook Air, and as expected, the header does not reveal any additional information about these new events.</div><div><br class="webkit-block-placeholder" /></div><div>However, we have a solution for this. Steve Nygard's excellent <a href="http://www.codethecode.com/projects/class-dump/">class-dump</a> which allows us to inspect a particular framework for it's symbols. Naturally, being the curious person I am, I ran this against the Macbook Air's version of AppKit (949.18.0 if you're curious). After a short wait (AppKit is very large after all), the results poured out into a freshly pressed text file. I immediately searched for the word "swipe", chosen completely at random. What I found, was worth it's weight in gold... assuming you want to implement gestures.</div><div><br class="webkit-block-placeholder" /></div><div><div>- (void)magnifyWithEvent:(id)fp8;</div><div>- (void)rotateWithEvent:(id)fp8;</div><div>- (void)swipeWithEvent:(id)fp8;</div><div>- (void)beginGestureWithEvent:(id)fp8;</div><div>- (void)endGestureWithEvent:(id)fp8;</div><div><br class="webkit-block-placeholder" /></div><div>These new methods belong to NSResponder, which means that every single responder now supports these gesture events. That's pretty awesome. My immediate reaction was to set symbolic breakpoints for these symbols and to perform some gestures using my little test application. As expected, they were hit, and I checked out the backtrace. The only thing of interest was a new private method for NSApplication -- <span class="Apple-style-span" style="font-style: italic;">_handleGestureEvent: </span></div></div><div><div><div>called from NSApplication's <span class="Apple-style-span" style="font-style: italic;">-(void)sendEvent:(NSEvent *)anEvent</span> method.</div><div><br class="webkit-block-placeholder" /></div><div>Just to confirm this assumption, I overrode this method and just logged events from it. Turns out the only events that come through this method are gestures. Awesome. Interestingly enough, there is a small observation to be made here. Since every gesture passes through here, one could actually replace these gesture events with any other event, so you could get some free custom gestures by replacing the gestures with say, a keyboard shortcut event before passing it down the responder chain. Nothing really fantastic, but nice to note if you feel like playing with private methods. </div><div><br class="webkit-block-placeholder" /></div><div>So finally, we have everything we need to implement gestures for any NSResponder based object. Simply override the appropriate method for your gesture (swipe, pinch [magnify], or rotate), you can grab the value out of the NSEvent using the corresponding methods:</div><div><br class="webkit-block-placeholder" /></div><div>Swipe : <span class="Apple-style-span" style="font-style: italic;">-(float)deltaY</span>; <span class="Apple-style-span" style="font-style: italic;">-(float)deltaX</span>;</div><div>Magnification : <span class="Apple-style-span" style="font-style: italic;">-(float)deltaZ</span>; <span class="Apple-style-span" style="font-style: italic;">-(float)magnification; </span></div><div>Rotation : <span class="Apple-style-span" style="font-style: italic;">-(float)rotation</span>;</div><div><br class="webkit-block-placeholder" /></div><div>These methods return various values for each type of event depending on the type of event, velocity of movement and/or direction of movement. Some interesting notes here - swipes can be detected to the left or right as expected, but also <span class="Apple-style-span" style="font-style: italic;">up and down. </span>Pretty cool. I also suspect that the two methods under magnification actually return the same value, but I haven't checked. The value logged with the event is deltaZ, however. Rotation is pretty self explanatory. The actual values these methods return is a little bit more of a mystery. Swipe is straight forward, 1.0 for right, -1.0 for left, 1.0 for up, and -1.0 for down, depending on whether you check deltaX or deltaY respectively. Magnification and rotation both return various positive or negative values depending on the rotation or scale of magnification. You'll just kind of have to play with these, I couldn't discern a good pattern. However, there are two methods on NSEvent: <span class="Apple-style-span" style="font-style: italic;">-(float)standardRotationThreshold</span> and <span class="Apple-style-span" style="font-style: italic;">-(float)standardMagnificationThreshold </span>which I'm sure return some magic values that allow you to determine the angle and scale for the gestures, which I imagine can help you figure out what you need to do to your responder as a result of the gesture. Additionally, NSEvent adds <span class="Apple-style-span" style="font-style: italic;">-(BOOL)isGesture</span>, which as expected, lets you determine if an event is a gesture. NSResponder also adds gesture masks via <span class="Apple-style-span" style="font-style: italic;">-(unsigned long long)gestureEventMask</span> and <span class="Apple-style-span" style="font-style: italic;">-(void)setGestureEventMask:(unsigned long long)aMask </span>which presumably deal with the specific masks regarding events. </div><div><br class="webkit-block-placeholder" /></div><div>So, that should pretty much do it. You should be armed and ready to go to write some amazing code to take advantage of the trackpad inside the Macbook Air, and hopefully coming soon to a Macbook and Macbook Pro near you. Before anyone asks, this code will NOT work on current Macbook models, at least not on the current build of Leopard. It's possible when this AppKit version begins shipping standard (10.5.2, I suspect) that we may be able to fake these events with the old trackpads, depending on how much information we can squeeze out of AppKit. </div><div><br class="webkit-block-placeholder" /></div><div>Finally, I've built a small <a href="http://www.cocoadex.com/files/GestureTest.zip">project</a> based on the all of this code that will allow those of you lucky enough to have your Macbook Air already to see it all in action. It's fairly simple, just filling a simple custom view with a color based on the gesture you perform, but it is set up as a great test bed for playing around with third party gestures. In addition it has a commented out private method from NSApplication to log all the gesture events if you want to see them. Obviously if you uncomment this method, the events won't be processed and the color won't change since it's not sending them down the chain. I'll leave it as an exercise to the reader to add that. ;)</div><div><br class="webkit-block-placeholder" /></div><div>Thanks to everyone at my local Apple Store for their help, and the Macbook Air. Hopefully this will help everyone get their applications ready for multi-touch trackpads before they are everywhere.</div><div><br class="webkit-block-placeholder" /></div><div>Be back soon.</div><div><br /></div><div><br /></div></div></div></div>]]>
        
    </content>
</entry>

<entry>
    <title>Lemur Math</title>
    <link rel="alternate" type="text/html" href="http://cocoadex.com/2008/01/lemur-math.html" />
    <id>tag:cocoadex.com,2008://4.8</id>

    <published>2008-01-21T02:31:11Z</published>
    <updated>2008-02-03T01:52:49Z</updated>

    <summary>Mike Lee, of Delicious Monster fame, has a thrown up a tantalizing post concerning Core Animation and lemurs. Being a member of the Founding Troop myself, and an avid lover of OpenGL and Core Animation, I just had to check it out.Mike...</summary>
    <author>
        <name>Elliott</name>
        
    </author>
    
        <category term="Cocoa" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://cocoadex.com/">
        <![CDATA[<a href="http://www.twitter.com/bmf">Mike Lee</a>, of <a href="http://www.delicious-monster.com/">Delicious Monster</a> fame, has a thrown up a tantalizing <a href="http://atomicwang.org/motherfucker/Index/B4E5D81C-A9A0-403C-B7A3-62FEB81DE777.html">post</a> concerning Core Animation and lemurs. Being a member of the Founding Troop myself, and an avid lover of OpenGL and Core Animation, I just had to check it out.<div><br class="webkit-block-placeholder" /></div><div>Mike offers up a fantastic way of leveraging Core Animation to almost perfectly capture the essence of the Dashboard-liquifying, delicious flips the iPhone pulls off. Now then, while I am totally not the biggest math buff, I do have some background in the mathematics behind computer graphics, so I thought I'd offer up a more in depth explanation of the "<a href="http://www.lucasnewman.com/">Newmanian Physics</a>" at work here. </div><div><br class="webkit-block-placeholder" /></div><div>So, let's dive right in.</div><div><br class="webkit-block-placeholder" /></div><div>Mike begins the breakdown of the actual numbers process thusly:</div><div><br class="webkit-block-placeholder" /></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">Luckily I used to work with this insane genius named Lucas, who discovered that if you put a very small value into "m34" of Core Animation's CATransform3D struct, then scale the layer just right, you get a decent facsimile of the iPhone flip.</blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><br class="webkit-block-placeholder" /></blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">Since m34 doesn't sound very good in conversation, I think of this at the "Newman factor." The resulting distortion is, therefore, "Newman distortion," and the units in which it is adjusted are Newmans. One Newman is equal to the inverse of the distortion, which I'm pretty sure is math-speak for <span class="Apple-style-span" style="font-style: italic;">transform.m34 = 1/distortionInNewmans</span>. In other words, the more Newmans you have, the less the distortion.</blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><span class="Apple-style-span" style="color: rgb(0, 0, 0); font-family: Times; font-size: 16px; "><div class="paragraph Body" style="overflow-x: visible; overflow-y: visible; color: rgb(73, 59, 59); font-family: HoeflerText-Regular, 'Hoefler Text', 'Times New Roman', serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0px; line-height: 17px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; opacity: 1; padding-bottom: 0px; padding-top: 0px; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; "></div><div class="paragraph Body" style="overflow-x: visible; overflow-y: visible; color: rgb(73, 59, 59); font-family: HoeflerText-Regular, 'Hoefler Text', 'Times New Roman', serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0px; line-height: 17px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; opacity: 1; padding-bottom: 0px; padding-top: 0px; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; "><br class="webkit-block-placeholder" /></div></span></blockquote><div>If we look at the <a href="http://developer.apple.com/documentation/GraphicsImaging/Reference/CALayer_class/Introduction/Introduction.html">documentation</a> for the CATransform3D struct (hidden at the bottom of CALayer mind you), we notice that it is simply a struct representing a 4x4 matrix of CGFloats. These are logically numbered as most elements of matrices are - an 'm', followed by the row number, and then the column number. Thus, the Newman factor, as described by Mike corresponds to the third row and fourth column of our 4x4 matrix.</div><div><br class="webkit-block-placeholder" /></div><div>Now then, the more pedantic among you might notice that we are using a 4x4 matrix, and not a 3x3 matrix as would be logical given that we are in 3D space - that is, we are working with x, y, and z components, and that in Mike's example we are actually working with this seemingly useless fourth column vector to produce the desired effect. This fourth column vector (m14, m24, m34, and m44 for those keeping track) is where our adventure starts.</div><div><br class="webkit-block-placeholder" /></div><div><span class="Apple-style-span" style="font-weight: bold;"><span class="Apple-style-span" style="font-family: '-editor-proxy';">Homogenous Coordinates</span></span></div><div><br /></div><div>So, in math, as in computer graphics, this additional vector constitutes what are called homogenous coordinates. Roughly speaking, this equates to representing an N-D matrix using an N+1-D matrix, in order to capture an affine transform into a matrix form. Since modern graphics APIs work with matrices, modern graphics hardware is designed to work with matrices at a blindingly fast rate. Thus, in order to optimize affine transformations, being able to express them as matrices is <span class="Apple-style-span" style="font-style: italic;">extremely </span>important.</div><div><br class="webkit-block-placeholder" /></div><div>Now then, I know what you are saying to yourself. Elliott, what the hell is an affine transformation? Glad you asked! At it's most basic level, an affine transformation is a linear transformation, followed by a translation. Linear transformations in N space are represented by a single NxN matrix. The follow up translation is represented by a single column vector (in matrix form) which is where the additional column comes from. Now then, you are probably wondering about the additional row - this row represents a projection vector. </div><div><br class="webkit-block-placeholder" /></div><div>I'll explain if you are interested, if not, you can safely skip this part, just know that the projection vector is important for OpenGL/DirectX, and that it results in the additional row - and completion of our 4x4 matrix. </div><div><br class="webkit-block-placeholder" /></div><div><span class="Apple-style-span" style="font-weight: bold;">Perspective Projection</span></div><div><br class="webkit-block-placeholder" /></div><div>Now then, the addition of the fourth coordinate (for each column vector, representing a point in space), means that we are technically working as if we were in 4D. This is useful for projection of a 3D scene, as we can refer to any point by it's 4D coordinates (x, y, z, w). Now then, assume we have two planes. We can refer to these two planes by their value of w, as that is the only actual thing that varies between them. So, if we refer to the difference between these two planes in terms of w, let's say, w = 1 for one plane, and w = k for another plane. It doesn't really matter what k is, just that it isn't (or it could be) 1. </div><div><br class="webkit-block-placeholder" /></div><div>Now then, our point can be expressed on either plane using the same x, y, and z coordinates so long as they are expressed correctly in terms of w = 1, that is that w = 1 is the base for the projection. Thus to relate the two points, (x, y, z, 1) and (x, y, z, k) we can simply divide each coordinate by k. </div><div><br /></div><div>So, we get - (x, y, z, 1) == (x/k, y/k, z/k, 1). Pretty simple right? Awesome. As I said before, for our purposes, this doesn't really matter, but if you are really curious, this is very important in perspective projection, i.e. the effect of an object that is "farther" from you being projected at a smaller ratio. This additional row allows you to model this perspective projection into the matrix model, which, as before, is very useful.</div><div><br class="webkit-block-placeholder" /></div><div><span class="Apple-style-span" style="font-weight: bold;">Does Your Head Hurt Yet?</span></div><div><span class="Apple-style-span" style="font-weight: bold;"><br class="webkit-block-placeholder" /></span></div><div>Alright! So now that I've justified to you that 4x4 matrices are necessary, we can continue with this lemury math lesson. Looking back to what Mike talked about, we see that the component at the <span class="Apple-style-span" style="font-style: italic;">third row</span> and <span class="Apple-style-span" style="font-style: italic;">fourth column</span> is being modified to create this effect. As per above, this corresponds to the additional translation in our affine transformation to the z coordinate. </div><div><br class="webkit-block-placeholder" /></div><div>This actually turns out to be an exact equivalent of a common OpenGL command - glTranslate3f(x, y, z) on the current matrix, which is actually the identity, as per Mike's source code. In addition, this is applied as a sublayer transformation, which means that it affects all of the sublayers on the layer it is set on, but of course, not the actual layer. The layer that this <span class="Apple-style-span" style="font-weight: bold;">is</span> set on, is in the fact the content view's layer, which means that this transformation happens to -- tada, the images.</div><div><br class="webkit-block-placeholder" /></div><div>But the real question, is what does this actually do? Great question. This is the first part, of a [not-so] tricky two part matrix multiplication. You see, this translation does not in fact produce the actual flip. It is simply a perspective correction in the form of a translation after another component of this <span class="Apple-style-span" style="font-weight: bold;">single affine transform.</span> That's right, the power of Core Animation and math combine to let you do amazing things with a single transform. Your graphics card can do a freakin' bazillion million of these a second. The other part, coincidentally, is a rotation around the Y-axis, just as Mike discussed Dashboard widgets perform. This matrix is fairly common, and is useful to keep in mind when working with Y-axis rotations.</div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><div><div><div><br /></div><div><span class="mt-enclosure mt-enclosure-image"><img alt="lemur_math1.png" src="http://cocoadex.com/images/lemur_math1.png" width="300" height="200" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span></div></div></div><div><br /></div></blockquote><div>Where a is the angle of rotation, in our case, 180 degrees or π radians.. So, turning back to the example at hand. The other part of the affine transformation is handled in the form of flipAnimation from Mike's code. This code proceeds to rotate the front view and back view (in this case, two different images) in opposite directions so as to give the sensation of the one image flipping "over" to reveal the other image. As per Mike's post, in reality this would cause the object (an image) to actually move <span class="Apple-style-span" style="font-style: italic;">towards</span> us. However, what we expect and what we get aren't quite in sync. Since a computer display is just a projection of these images, we get a rather dull and uninteresting simple y-axis rotation, where we can't actually notice that the image should be moving towards us. If you imagine several planes, each one representing a computer display, the image would have realistically moved between one plane and another plane in the Z-direction (in this case, positive Z, coming <span class="Apple-style-span" style="font-weight: bold;">out </span>of your computer display, and thus representing the expected forward movement). </div><div><br class="webkit-block-placeholder" /></div><div><span class="Apple-style-span" style="font-weight: bold;">@finally</span></div><div><br class="webkit-block-placeholder" /></div><div>Alright, so now we have discovered the source of the majority of the flip, but remember, we still have that little Z translation floating around. So, if we combine the two to create our final affine transformation matrix, we get a matrix that looks like this. Let's define X as (1/DN).</div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><br /></blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><span class="mt-enclosure mt-enclosure-image"><img alt="lemur_math2.png" src="http://cocoadex.com/images/lemur_math2.png" width="300" height="200" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span></blockquote><div><br class="webkit-block-placeholder" /></div><div>Where DN is Distortion in Newmans. Now, you might notice that the inverse of distortion in Newmans is actually negative! This is pretty surprising, as Mike definitely set the distortion in Newmans to be the positive inverse of DN. How did this happen? Well, if we split this matrix back into the two matrices that formed them, we get:</div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><br /></blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><span class="mt-enclosure mt-enclosure-image"><img alt="lemur_math3.png" src="http://cocoadex.com/images/lemur_math3.png" width="300" height="200" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span></blockquote><div><br class="webkit-block-placeholder" /></div><div>For the rotation. And</div><div><br class="webkit-block-placeholder" /></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><span class="mt-enclosure mt-enclosure-image"><img alt="lemur_math4.png" src="http://cocoadex.com/images/lemur_math4.png" width="300" height="200" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span></blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><br class="webkit-block-placeholder" /></blockquote>For the translation. Notice, still rocking the positive 1/DN. However, if you pull out that dusty old Linear Algebra textbook, and run matrix multiplication on these two matricies, you will notice that the negative values in the rotation matrix cause the 1/DN to become negative. In this case, this is interesting because we happen to have a positive Z increase from our Y-axis rotation that is being unrealistically removed from due to the projection onto our display. This, as Mike puts it, is fine when you are not rendering at full screen, but because you will clip over the edges on full screen, completely ruins the experience on a device like an iPhone.<div><br class="webkit-block-placeholder" /></div><div>So, what are we to do? Why, correcting for that inaccuracy seems like a good idea. That's exactly what Mike's code does. Since the final matrix actually creates that negative Z value that we are looking for, it will slowly move the image "away", creating a realistic perspective correction. This is noticed very easily by turning on Mike's debugging mode with a distortion value of ~2500, as in his example, and noticing the arc backwards created by the rotating origin. If you go back and comment out this code, you'll notice the origin follows a straight line across the X axis, resulting in the unrealistic transform we don't want. </div><div><br class="webkit-block-placeholder" /></div><div>So why does this work? Well, it's most easily demonstrated by looking at the application run in debug mode, however what we are really doing is defining a final value that we want Core Animation to have as the transformed Z value, and Core Animation smoothly animates to that value, which ends up rendering a curve as the component is "animated" over time. </div><div><br class="webkit-block-placeholder" /></div><div>If we look at the different values for distortion, we can see the differences in curves. as the ratio 1/DN gets lower and lower, we get a smoother and smoother Z-curve, obviously the point of being too smooth -- to where we don't get a realistic enough curve. To my knowledge, there is no magic ratio for this number. However, I've come up with an interesting little equation, which I think gives a decent recommended Newman Distortion value. I call it the Harris-Lee General Equation for Newman Distortion.</div><div><br /></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">ND = 1 / ((Layer.Height / Layer.Width) / 1000)</blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><br class="webkit-block-placeholder" /></blockquote>This equation is a general equation, meaning it will work on all displays. However, rendering as an art is derived from the aspect ratio of the screen you are rendering on. In addition, we must have a consistent aspect ratio from the layer. With this in mind, we can actually derive a much more precise equation, which can be fine tuned for precise animations.<div><br class="webkit-block-placeholder" /></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">float layerRatio = 0.0;</blockquote><div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">if(Layer.Height &gt; Layer.Width)</blockquote></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">layerRatio = Layer.Width / Layer.Height;</blockquote>else if(Layer.Height &lt;= Layer.Width)</blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">layerRatio = Layer.Height / Layer.Width</blockquote><br class="webkit-block-placeholder" /></blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">float maxScreen = 0.0;</blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">if(Screen.Height &gt; Screen.Width)</blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">maxScreen = Screen.Height;</blockquote>if(Screen.Width &gt; Screen.Height)</blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">maxScreen = Screen.Width;</blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><br class="webkit-block-placeholder" /></blockquote>ND = 1 / (layerRatio / maxScreen);</blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><br class="webkit-block-placeholder" /></blockquote>Let's just plug in some values, based on my own display resolution (1440x900), and the size of the test image (300x400). <div><br class="webkit-block-placeholder" /></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">ND = 1 / (0.75 / 1440)</blockquote><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">ND ~= 2000;</blockquote><div><br class="webkit-block-placeholder" /></div>You'll notice this value is very close (relatively speaking) to the magical 2500 number that Mr. Lee came up with. Upon close inspection it gives a pretty smooth curve, and is mathematically derivable. Disclaimer: I have no idea if this is right, but I suspect it works.<div><br class="webkit-block-placeholder" /></div><div><span class="Apple-style-span" style="font-weight: bold;">@conclusion</span></div><div><br class="webkit-block-placeholder" /></div><div>Hopefully, despite being long winded, I've shed some light on what exactly is going on. I'd like to thank Mike Lee, Lucas Newman, and Wil Shipley for pushing the envelope of what's possible with Core Animation. Apple for creating Core Animation. <a href="http://mooseyard.com/Jens/2008/01/gone-indie/">Jens Alfke</a>, for inspiring me to become a Mac programmer, and finally my Computer Graphics professors for making me cram all this stuff into my head before they let me graduate in December.</div><div><br class="webkit-block-placeholder" /></div><div>Be back soon!</div><div><br /></div><div>Edit: Updated with better matrices for posterity and non-embarrassment. </div>]]>
        
    </content>
</entry>

<entry>
    <title>Welcome to 2008.</title>
    <link rel="alternate" type="text/html" href="http://cocoadex.com/2008/01/welcome-to-2008.html" />
    <id>tag:cocoadex.com,2008://4.7</id>

    <published>2008-01-01T07:49:30Z</published>
    <updated>2008-01-01T07:52:39Z</updated>

    <summary>Hey everyone.  Welcome to the overhaul and relaunch of my blog. One of my New Year&apos;s Resolutions was to completely redesign and restructure my blog, and to actually start using it. So, here it is! Over the next few days,...</summary>
    <author>
        <name>Elliott</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://cocoadex.com/">
        <![CDATA[Hey everyone.  <div><br class="webkit-block-placeholder" /></div><div>Welcome to the overhaul and relaunch of my blog. One of my New Year's Resolutions was to completely redesign and restructure my blog, and to actually start using it. So, here it is! Over the next few days, I'm going to fill out the content. The look of the blog is based on the old look, and of course some influences from my favorite blogs. I tried to keep it as simple as possible, and I think it came out pretty well. Undoubtedly, I'll be tweaking some of the design here and there, but the overall idea is there. </div><div><br class="webkit-block-placeholder" /></div><div>I hope everyone has a great year!</div>]]>
        
    </content>
</entry>

</feed>
