Thursday, February 24, 2011

QuickBoot

If you're going to install the 10.7 preview on a separate hard drive or partition, it's definitely worth knowing about Buttered Cat Software's QuickBoot, which allows you to change startup disks and reboot from your menu bar.



Lion in the House

Today, Apple released a preview version of Mac OS X Lion, but only for registered Mac developers. This is a big release, not just in terms of front-end experience, but also under the hood. A lot of the changes are influenced by UIKit and iOS, hence the moniker "Back to the Mac", but there's also a fair amount of completely new goodness, some of which will likely roll down to iOS at some point.

If you're an iOS developer, but not a Mac developer, it's probably worth $99 to get access to Tiger Lion. It'll give you a better idea of where Apple is taking things.

Plus, there's just a lot of really cool stuff in there.

Interestingly, the OS preview is being delivered via the Mac App Store, which might be a hint at how paid OS upgrades will be handled in the future.

Members of the Mac developer program can log into the Mac Developer site to download Lion, the release notes, and a new version of Xcode 4.



Wednesday, February 23, 2011

Voices that Matter Seattle

So far, 2011 has been pretty light for me in terms of speaking. I do, however, have one speaking engagement lined up for this year: I'll be speaking at Voices that Matter in the land of Mordor Seattle on April 9th and 10th. If you're interested in going, early bird pricing ends on February 25.

You can use the speaker code SEASPK2 to get $100 off.

There's a great speaker lineup for this conference, including Andy Ihnatko.



Tuesday, February 22, 2011

Blender 2.5 beta 6 Objective-C Export

A kind reader updated my Objective-C export script for Blender to work with the 2.5 beta 6 version of Blender. You can find the new version on GitHub.

On a related note, if you make a change to your clone of any of my public repositories on Github, you can send me a pull request. I'm happy to take additions, bug fixes, and other updates back into the master repository.

Thanks to John Becker for updating the script!



Apple Outsider on the Subscription "Hubbub"

I have a very short list of "must-read" blogs. While I have a much bigger list of blogs I read as time permits, the list of ones that I check every morning before I buckle down to work consists of only about a half-dozen blogs by people in our industry who really know their stuff. One of those blogs is Apple Outside, written by former Apple Evangelist, Cocoa Guru, and all-around nice guy Matt Drance (not to be confused with the more intimidating BatDrance who is most definitely not Matt's alter-ego).

I've been keeping my head low on the whole subscription kerfuffle that's been happening in the iOS dev world. Partially that's just because I'm busy and don't have time to pen a long blog-rant, but it's also because it's a complex situation on which I don't have a fully-formed opinion yet. Matt's even-handed take on the situation does a great job of articulating the situation and is well worth reading.





Tuesday, February 15, 2011

A Couple CGAffineTransform Goodies

Thanks to Core Animation, we iOS programmers tend to use affine transformations (by way of CGAffineTransform) a lot. By being able to combine multiple 2D transformations into a single matrix, we have the ability to do a lot of cool animation effects with only a few lines of code.

Take the following example, which is fairly typical:

    CGAffineTransform transform = CGAffineTransformMakeTranslation(0, -translation);
transform = CGAffineTransformScale(transform, scaleFactor, scaleFactor);
view.transform = transform;


Not bad, right? In just three lines of code, we're able to both scale and translate a view or layer. But in reality, there's actually quite a few operations going on behind these three lines of code. The CGAffineTransformScale() function calls CGAffineTransformConcat() to perform a matrix multiplication operation between two affine matrices. But, as you probably know, you can't multiply a 2x3 matrix by another 2x3 matrix. To multiply affine transformations, they have to be converted back to 3x3 vector matrices first.

On today's devices (even mobile devices), this all takes a trivial amount of processing power. But sometimes, when you're doing a lot of these transformations — say thousand or tens of thousands a second — it can be valuable to be able to avoid that conversion and matrix multiplication.

It just so happens that with certain commonly used CGAffineTransforms, you can cheat. Certain matrices can be joined together without performing matrix multiplication. For example, here are the matrices created by CGAffineTransformMakeScale() and CGAffineTransformMakeTranslation(), respectively:

Equation08           Equation06


Go ahead and multiply those two together. Plug in any number for tx, ty, sx, and sy and run the numbers. I'll wait. Okay, you don't have to. This is what you'll get:
Equation0x

So, if that's the result we're going to get, why bother going through the matrix multiplication in the first place? Why not just populate the matrix with both the scale and translate values right from the get-go? Well, we can. We can also do the same thing with translate and rotate.

This is all there is to it:

static inline CGAffineTransform CGAffineTransformMakeRotateTranslate(CGFloat angle, CGFloat dx, CGFloat dy)
{
return CGAffineTransformMake(cosf(angle), sinf(angle), -sinf(angle), cosf(angle), dx, dy);
}

static inline CGAffineTransform CGAffineTransformMakeScaleTranslate(CGFloat sx, CGFloat sy, CGFloat dx, CGFloat dy)
{
return CGAffineTransformMake(sx, 0.f, 0.f, sy, dx, dy);
}


That's it. It only saves you two lines of code:

    view.transform = CGAffineTransformMakeScaleTranslate(scaleFactor, scaleFactor, 0, -translation);


But, your stack allocation is considerably smaller (one CGAffineTransform instead of two CGAffineTransforms and an intermediate 3x3 array. It also saves you eighteen floating point multiplications and nine floating point additions. 99.9% of the time, that number of operations is going to have no noticeable affect on your application - it's a trivial amount of both memory and FLOPS under most normal situations.

But… if you're doing a lot per second, they can add up and it's nice to know there's a way that you can save yourself a little overhead in some situations.



Sunday, February 13, 2011

Xcode 4 Icons

Well, now that Xcode 4 is GM, it has the same icon as Xcode 3.25. Ordinarily, this wouldn't be an issue, since a GM release means you can throw out the old one and use it full-time.

Only, you may not be able to with all of your projects. Xcode 4 GM has a few issues that make it hard to go full-time with it, including a linker error that can only be worked around by turning some level of code optimization, a change that makes it hard to debug. A few of these problems impact projects I'm working on, so as a result, I have to grudgingly use Xcode 3.25 for some tasks.

Despite a small handful of problems, though, Xcode 4 is where I want to be whenever possible. Having multiple identical icons in your Dock can be a bit of a pain.

Unfortunately, I didn't save the old Xcode 4 installers. If I had, I would have just gone and stolen the old preview icon and continued using that. Since I didn't, I did the same thing I did for beta iOS releases and made a customized version of the app icon for Xcode 4. If you want to use it, you can download it here. To install, you just copy the .icns file into Xcode 4's app bundle, replacing the existing one. And, no, replacing the icon file with a new one doesn't cause problems with Xcode 4 due to code signing, though I feared it might.

This is what it looks like:

Xcode




Tuesday, February 8, 2011

MC3D - Platform Agnostic 3D Foundation

Sorry for the lack of posts recently. Things have been, well… you know. Same old story. Super busy. Which is good, but it's murder on blog post frequency.

I've recently had to port some OpenGL ES work I did from iOS to Android. It used to be that doing so would have been insanely painful (as opposed to just painful). I would have had to convert the Objective-C code to Java, and then maintain completely distinct sets of code that do the same exact thing. Fortunately, the Android NDK (Native Development Kit) allows you to write code for Android in C/C++. The version of the NDK supported on 2.2 still requires part of the Activity (Android's counterpart to an iOS view controller) to be written in Java, but does allow you to call C/C++ code using JNI. In 2.3 and 3.0, you can do entire activities in C or C++.

This is a huge step forward for Android for those of us who do performance-critical work on multiple platforms, but it's not without some pain. Debugging across the JNI bridge is… less than easy. But, being able to share code across platforms is a huge win, and being able to get native speeds in the process is teh awseome.

During these projects, I've been taking a lot of my 3D-related code and creating a new set of platform-agnostic C functions and types. I've been cleaning up and making names consistent, and placing appropriate pre-compiler macros to make sure the code compiles correctly everywhere. On iOS, the library will take advantage of the Accelerate Framework in places, but doesn't require Accelerate to function.

I've chosen C because I don't like mixing C++ and Objective-C. The object models are too different for my tastes. But I've also made sure to include proper ifdef'd extern statements so that you can import the MC3D header files from C++ without hassle.

I've dubbed this set of functions MC3D, and I'm making it open source under a simplified version of the simplified BSD license (simplified simplified BSD license?). I've taken out the attribution requirement, so the only requirement is that if you re-distribute the source code, you have to leave the copyright and license text intact. That's it. Otherwise, you can use it for free in any project, commercial or otherwise, without paying anything, without attributing, and without asking (no really, you don't need to ask).

MC3D is still very much a work in progress, and I'm only adding code to the repository that I feel is ready for public consumption. Much of what's in MC3D has been posted here before, sometimes with different names or in slightly different form.

I have other code that I plan to add in the future, including higher-level functionality like model loading, scene management, and skeletal animation, but I won't add anything until its both solid and platform agnostic.

Currently, documentation is very sparse, and I currently can't offer any support or help with using it, so caveat emptor! I will gladly accept contributions, bug fixes, and new functionality back into the MC3D codeline.

MC3D on GitHub.

Link fixed, sorry about that