For those of you having trouble running the application, I've also added i386 to the supported architectures. Because of my use of blocks, Snow Leopard is required to run the app.
Ipod Touch Review
# # 8 GB capacity for about 2,000 songs, 10,000 photos, or 10 hours of video # Up to 40 hours of audio playback or 7 hours of video playback on a single charge # Support for AAC, Protected AAC (iTunes Store) and other audio formats; H.264, MPEG-4,
Ipod Touch Review
# One-year limited warranty # iPod touch has 8 GB capacity for about 2,000 songs, 10,000 photos, or 10 hours of video. # iPod touch has a 3.5-inch (diagonal) widescreen Multi-Touch display with 960-by-640-pixel resolution (326 pixels per inch). › See more technical details.
Ipod Touch Review
# iPod touch has one-year limited warranty. # IPod touch plays up to 40 hours of audio playback or 7 hours of video playback on a single charge. # Motion JPEG video codecs in M4V, MP4, MOV, and AVI formats
Tampilkan postingan dengan label Open Source. Tampilkan semua postingan
Tampilkan postingan dengan label Open Source. Tampilkan semua postingan
Sabtu, 30 Oktober 2010
Tile Cutter Updated
Had to re-tile a large image, so spent a bit of time converting tile cutter to use NSOperationQueue. After a little playing, I opted for one operation per row, which seems to give the best all-around performance for the widest variety of images. You can download the latest version from here, or pull the source from GitHub.
For those of you having trouble running the application, I've also added i386 to the supported architectures. Because of my use of blocks, Snow Leopard is required to run the app.
For those of you having trouble running the application, I've also added i386 to the supported architectures. Because of my use of blocks, Snow Leopard is required to run the app.
Selasa, 19 Oktober 2010
Tile Cutter Updated
Today, I released a new version of Tile Cutter. This is just a bug-fix release; the changes have been pushed to GitHub.
OpenGL ES iOS
I've created a new public project on GitHub for classes, scripts, and projects related to OpenGL ES programming on the iPhone. I'll be slowly consolidating all of my OpenGL ES code snippets, utilities, and sample projects except for the particle generator (which has its own repository) into this location.
Right now, all it has is:
Right now, all it has is:
- Blender export script for Objective-C for Blender 2.49a
- Blender export script for Objective-C for Blender 2.5+
- My old OpenGL ES Xcode project template for OpenGL ES 1.1
- A fairly simple OpenGL ES 1.1 Xcode project
- A fairly simple OpenGL ES 2.0 xcode project
- A few OpenGL ES-related categories and classes
- My old Wavefront OBJ file loader
Sabtu, 09 Oktober 2010
Tile Cutter Open Sourced
I have open-sourced Tile Cutter under the MIT license and put it on Github as a public project. This application was written extremely quickly (less than half a day) because I needed the functionality for a client project, so there are several things about this application that are klugey, including some uncomfortable crossing of the boundaries between what a view should do and what a controller should.
But, it works, and I don't see myself having time to go clean it up anytime soon, so I'm donating it to the public good, warts and all. I welcome back any enhancements, bug fixes, or modifications, but you are not required to give anything back under the license.
But, it works, and I don't see myself having time to go clean it up anytime soon, so I'm donating it to the public good, warts and all. I welcome back any enhancements, bug fixes, or modifications, but you are not required to give anything back under the license.
Jumat, 21 Mei 2010
Gradient Buttons Yet Again
I added two more button styles to the iPhone Gradient Buttons project and made stroke color and stroke weight configurable options. The two new styles look exactly like the old Black and White style, only the highlight state is a blue gradient. These simulate the style used in alert sheets in several Apple applications.

Some of the Core Graphics code was machine-generated and is in kind of rough shape, but it works. I'm thinking about refactoring the different styles methods into something shorter, perhaps a plist, or just C arrays with the different numeric values.
For some strange reason, when I try to use arrayWithObjects: instead of creating a mutable array and manually adding the colors one at a time, I get a NULL gradient back. I have no idea why, but it's working this way at least.
Anyone who wants to contribute, let me know, I'd be happy to add committers.

Some of the Core Graphics code was machine-generated and is in kind of rough shape, but it works. I'm thinking about refactoring the different styles methods into something shorter, perhaps a plist, or just C arrays with the different numeric values.
For some strange reason, when I try to use arrayWithObjects: instead of creating a mutable array and manually adding the colors one at a time, I get a NULL gradient back. I have no idea why, but it's working this way at least.
Anyone who wants to contribute, let me know, I'd be happy to add committers.
Rabu, 19 Mei 2010
Improved Gradient Buttons
I've been playing around a bit, improving my imageless gradient button class. The new version allows you to specify the gradient for the normal and highlighted state by populating two arrays, one with the colors that make up the gradients and another with the relative location for each color. I've gotten rid of the abstract parent class and individual child classes and all the functionality is now contained in a single class.

There are five built-in styles which can be seen in the image above, or you can manually set the gradient to any value you'd like. You can download the source codes from the Google code page. There are no restrictions or limitations on its use.
The easiest way to use these is to add a UIButton instance to your view in Interface Builder, then change the underlying class from UIButton to GradientButton. Because there's no way to create IB palettes for iPhone classes, you'll also have to implement viewDidLoad and set the gradient or use the existing methods there.

There are five built-in styles which can be seen in the image above, or you can manually set the gradient to any value you'd like. You can download the source codes from the Google code page. There are no restrictions or limitations on its use.
The easiest way to use these is to add a UIButton instance to your view in Interface Builder, then change the underlying class from UIButton to GradientButton. Because there's no way to create IB palettes for iPhone classes, you'll also have to implement viewDidLoad and set the gradient or use the existing methods there.
Selasa, 18 Mei 2010
Programmatic Gradient Buttons
Thanks to a little insomnia, I decided to play around a little more with doing a programmatic gradient button. I started to create another gradient button, realized that the code was going to be 90% the same between the two style gradient buttons, so did a little refactoring. The result is a class you can subclass to easily make new gradient buttons. All you have to do is override three methods to specify the gradient to use when the button is in its normal state, the gradient to use when the button is in highlighted (pressed) state, and the corner radius. Here's what the alert-style button looks like now:
BlueGradientButton.h
BlueGradientButton.m
Adding new gradient buttons is relatively simple, since all the heavy drawing is handled in the superclass based on the values you return in these three methods. You can check out the sample project that has two gradient buttons: one that simulates the alert style button and which also works for regular bar buttons, and one that simulates the red delete button. I'll likely add more styles later.
One important notice - the CFGradientRef returned by the two methods should not be released, the super class will release it when it's done. This is a bit of an oddity, but there is no CFGradientAutorelease() function, only a CFGradientRelease() function. I changed the name to start with "create". In the Core Foundation memory management rules, functions that use create return an object with retain count of 1. There probably is a more elegant way to deal with this situation, but none occurred to me and I didn't want to have to mess around with a callback to release the memory given how straightforward the usage is here.
You can download the project here. I've also added the project to Google Code if anyone wants to contribute additional elements.
BlueGradientButton.h
#import <UIKit/UIKit.h>
#import "AbstractGradientButton.h"
@interface BlueGradientButton : AbstractGradientButton
{
}
@endBlueGradientButton.m
#import "BlueGradientButton.h"
@implementation BlueGradientButton
- (CGGradientRef)createNormalGradient
{
CGFloat locations[3];
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
NSMutableArray *colors = [NSMutableArray arrayWithCapacity:3];
UIColor *color = [UIColor colorWithRed:0.283 green:0.32 blue:0.414 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[0] = 0.0;
color = [UIColor colorWithRed:0.82 green:0.834 blue:0.87 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[1] = 1.0;
color = [UIColor colorWithRed:0.186 green:0.223 blue:0.326 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[2] = 0.483;
CGGradientRef ret = CGGradientCreateWithColors(space, (CFArrayRef)colors, locations);
CGColorSpaceRelease(space);
return ret;
}
- (CGGradientRef)createHighlightGradient
{
CGFloat locations[4];
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
NSMutableArray *colors = [NSMutableArray arrayWithCapacity:4];
UIColor *color = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[0] = 0.0;
color = [UIColor colorWithRed:0.656 green:0.683 blue:0.713 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[1] = 1.0;
color = [UIColor colorWithRed:0.137 green:0.155 blue:0.208 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[2] = 0.51;
color = [UIColor colorWithRed:0.237 green:0.257 blue:0.305 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[3] = 0.654;
CGGradientRef ret = CGGradientCreateWithColors(space, (CFArrayRef)colors, locations);
CGColorSpaceRelease(space);
return ret;
}
- (CGFloat)cornerRadius
{
return 7.0;
}
@end
Adding new gradient buttons is relatively simple, since all the heavy drawing is handled in the superclass based on the values you return in these three methods. You can check out the sample project that has two gradient buttons: one that simulates the alert style button and which also works for regular bar buttons, and one that simulates the red delete button. I'll likely add more styles later.
One important notice - the CFGradientRef returned by the two methods should not be released, the super class will release it when it's done. This is a bit of an oddity, but there is no CFGradientAutorelease() function, only a CFGradientRelease() function. I changed the name to start with "create". In the Core Foundation memory management rules, functions that use create return an object with retain count of 1. There probably is a more elegant way to deal with this situation, but none occurred to me and I didn't want to have to mess around with a callback to release the memory given how straightforward the usage is here.
You can download the project here. I've also added the project to Google Code if anyone wants to contribute additional elements.
Rabu, 28 April 2010
iPhone Barcode Library
Chris of the Yeti Factory has ported my Cocoa Barcode library to the iPhone. This has been something I've been meaning to do for a while, but I'm actually kind of glad someone else did it. I wasn't relishing diving into eight-year old code.
Senin, 12 April 2010
Core Data Library
For quite some time, I've been thinking about ways to improve the use of UITableViewController. I experimented a bit with a property-list driven model, and then simplified that into the paired-array version that is in More iPhone 3 Development. One of the things on my "would like to do list" has been to revisit that and create a good, robust tool to make table-based editable detail views easier.
Somebody beat me to the punch though. I haven't tried it out yet, but first impressions are positive and it looks like a great tool for anyone writing apps with table-based detail views.
Somebody beat me to the punch though. I haven't tried it out yet, but first impressions are positive and it looks like a great tool for anyone writing apps with table-based detail views.
Senin, 21 September 2009
Dice Poker - Another One from the Dev Folder

Here's another Xcode project from the dusty corners of my dev folder. This is a project I wrote for an article Dave and I were going to write, but we decided on a different application.
As usual, typical warnings about not being production-ready, yada yada.
Jumat, 11 September 2009
Grand Central Dispatch is Open Source
I find this fascinating.
Apple has open-sourced libdispatch, better known to most people as Grand Central Dispatch.
Grand Central Dispatch is something that developers - at least those who attend WWDC - have known about for well over two years. It's not something that your typical computer user would get excited over, but from the perspective of a developer, it's a really exciting technology that allows you to leverage the power of all the processing units in a given machine relatively easily.
When I saw the GCD demo that Bertrand Serlet gave at WWDC 2008, I was blown away. I looked at it as a game changer for the long term. Until there's a huge breakthrough in chip technology, utilizing multiple cores and multiple processors is the way to improved performance and this looked like something that was going to launch them way ahead of everyone else.
I saw GCD as a huge competitive advantage for Apple. And now, they're giving it away under a fairly liberal open source license (theApple Open Source license, a variant of theApache license). They not only proposed a new standard, they're giving away the underlying implementation that's been in development for probably three or more years. Though I haven't looked at it, from some of the sessions I attended this year, it sounded like getting this working was quite an engineering feet
I think it's awesome, but I'm honestly surprised by it. Strategically speaking, it's an odd move. I see the benefit to Apple for having the block notation and syntax be an open standard. I'm having some trouble seeing the strategic benefit to letting other people use this amazing technology for free. I have to think this will buy at least a tiny amount of good karma from the Open Source community. Maybe.
Apple has open-sourced libdispatch, better known to most people as Grand Central Dispatch.
Grand Central Dispatch is something that developers - at least those who attend WWDC - have known about for well over two years. It's not something that your typical computer user would get excited over, but from the perspective of a developer, it's a really exciting technology that allows you to leverage the power of all the processing units in a given machine relatively easily.
When I saw the GCD demo that Bertrand Serlet gave at WWDC 2008, I was blown away. I looked at it as a game changer for the long term. Until there's a huge breakthrough in chip technology, utilizing multiple cores and multiple processors is the way to improved performance and this looked like something that was going to launch them way ahead of everyone else.
I saw GCD as a huge competitive advantage for Apple. And now, they're giving it away under a fairly liberal open source license (the
I think it's awesome, but I'm honestly surprised by it. Strategically speaking, it's an odd move. I see the benefit to Apple for having the block notation and syntax be an open standard. I'm having some trouble seeing the strategic benefit to letting other people use this amazing technology for free. I have to think this will buy at least a tiny amount of good karma from the Open Source community. Maybe.
Minggu, 06 September 2009
Backwards Compatible OpenGL ES 2.0
Here is an ambitious open source project intending to make OpenGL ES 2 code on the iPhone backward compatible. I haven't had time to check this out yet, but I plan to when I get some free time. It seems like this could be a godsend for developers facing the decision to use ES 1.1 or 2.0.
Kamis, 20 Agustus 2009
Property-List Driven Detail Editing Pane
A while back, I discussed using a property list to drive a table-based detail editing pane. I had intended to use this code in a sample project in More iPhone Development. I still feel strongly that this is a good approach, and when I have some time, plan to work on it more. However, from a pedagogical standpoint, it wasn't working for me. All of the code I needed to demonstrate was getting moved to generic classes and the main point was getting lost in a confusing mess of classes.
Therefore, since it's not going to be used in the book, I'm releasing the code for people to look at and use (no restrictions or requirements). Please note, however, that this is NOT production quality code, so caveat emptor. If you want to use this in a real application, expect to sink some time into extending and debugging. In the long run, I think you'll be happier than maintaining huge sets of nested case statements, however.
You can find the project here.
Therefore, since it's not going to be used in the book, I'm releasing the code for people to look at and use (no restrictions or requirements). Please note, however, that this is NOT production quality code, so caveat emptor. If you want to use this in a real application, expect to sink some time into extending and debugging. In the long run, I think you'll be happier than maintaining huge sets of nested case statements, however.
You can find the project here.
Rabu, 15 Juli 2009
Gah! Up is Down! Right is Wrong! Make it Stop!
Today, some programmer named Zed Shaw wrote a blog post titled Is BSD The [sic] New GPL?. The crux of his article is that because a few people have, dog forbid, proselytized for the BSD license and tried to get some other projects that are currently using the restrictive GPL license to switch to the BSD license because the viral GPL license prevents code from flowing equally in both directions between the projects that, therefore, the BSD license is now just as bad as the GPL.
What... the... Fuck?
Because a few people suggested that, hey, maybe you guys would consider dropping some of those restrictions on your code so we can all, like, share equally, Zed Fucking Shaw thinks that's exactly the same as a viral license that puts restrictions, in perpetuity, on the code you write as well as on all derivative products, and any code that happened to have been stored on the same hard drive as your product for a little while1. I'd expect anti-logic like this from a marketing executive, lawyer, or clergyman, but not from a programmer. This is a pathetic excuse for logic. It's Orwellian logic. Right is wrong. Up is down. It's not missing the point, it's closing your eyes and screaming "nah-nah-nah" so you can claim you're unaware of the fucking point.
Now, I'm a big fan of openness. Almost every line of code that I've ever written that wasn't written specifically for a client or employer has been released in some form, either under a liberal license like the BSD or MIT license or simply given out as public domain code2. But I have not used and will not use the GPL. In fact, when people ask me if they can include code I've written in a GPL'd project (which they don't have to do, so I do appreciate the gesture) I always grant permission, but specifically request that they document the fact that my code is not covered by the project license.
I'm not a fan of the GPL quite simply because I don't see the GPL as "open". The GPL is not defined by what it is, it's defined by what it isn't. It's "against" proprietary closed source code. It's against corporations. It's against software as a commercial product. It's all about what it's not. It's a political movement replete with a manifesto. No joke. A fucking manifesto. The GPL is about openness in the same way that Stalin was about peace and kindness. And you know what? I don't want my code tied up in a political movement. If I want to share, I'll happily share with no expectation of a direct return. If I don't want to (or can't) share, I won't publish my code.
Sir Isaac Newton uttered a very famous line long ago in what is one of the greatest displays of modesty ever recorded. He said, "If I have seen further it is only by standing on the shoulders of giants." And that modest statement sums up the way science, and all meaningful pursuit of knowledge works. Knowledge is expanded when it is shared. When solutions to problems are shared, that frees us up to tackle the next obstacle rather than spending time solving problems that have already been solved by others. Which, if you read their propaganda, is exactly what the GNU foundation people think they believe. But anyone who has actually read their license terms knows that obviously they don't, because you can't reconcile that with the viral restrictions in their licenses. If you truly believe that knowledge is not a zero-sum game, and that sharing knowledge tends to increase the sum of societal knowledge, then you don't go putting petty restrictions on your knowledge.
Sometimes, when you fight fire with fire, all you get is a bigger fire and you certainly don't put out a fire by loudly exclaiming that water is the new fire.
Footnotes
1 - Okay, I'm kidding about the last one.
2 - Well, that's not completely true. I also don't release code that I know is bad because I don't want people copying or learning from code I know has serious problems.
What... the... Fuck?
Because a few people suggested that, hey, maybe you guys would consider dropping some of those restrictions on your code so we can all, like, share equally, Zed Fucking Shaw thinks that's exactly the same as a viral license that puts restrictions, in perpetuity, on the code you write as well as on all derivative products, and any code that happened to have been stored on the same hard drive as your product for a little while1. I'd expect anti-logic like this from a marketing executive, lawyer, or clergyman, but not from a programmer. This is a pathetic excuse for logic. It's Orwellian logic. Right is wrong. Up is down. It's not missing the point, it's closing your eyes and screaming "nah-nah-nah" so you can claim you're unaware of the fucking point.
Now, I'm a big fan of openness. Almost every line of code that I've ever written that wasn't written specifically for a client or employer has been released in some form, either under a liberal license like the BSD or MIT license or simply given out as public domain code2. But I have not used and will not use the GPL. In fact, when people ask me if they can include code I've written in a GPL'd project (which they don't have to do, so I do appreciate the gesture) I always grant permission, but specifically request that they document the fact that my code is not covered by the project license.
I'm not a fan of the GPL quite simply because I don't see the GPL as "open". The GPL is not defined by what it is, it's defined by what it isn't. It's "against" proprietary closed source code. It's against corporations. It's against software as a commercial product. It's all about what it's not. It's a political movement replete with a manifesto. No joke. A fucking manifesto. The GPL is about openness in the same way that Stalin was about peace and kindness. And you know what? I don't want my code tied up in a political movement. If I want to share, I'll happily share with no expectation of a direct return. If I don't want to (or can't) share, I won't publish my code.
Sir Isaac Newton uttered a very famous line long ago in what is one of the greatest displays of modesty ever recorded. He said, "If I have seen further it is only by standing on the shoulders of giants." And that modest statement sums up the way science, and all meaningful pursuit of knowledge works. Knowledge is expanded when it is shared. When solutions to problems are shared, that frees us up to tackle the next obstacle rather than spending time solving problems that have already been solved by others. Which, if you read their propaganda, is exactly what the GNU foundation people think they believe. But anyone who has actually read their license terms knows that obviously they don't, because you can't reconcile that with the viral restrictions in their licenses. If you truly believe that knowledge is not a zero-sum game, and that sharing knowledge tends to increase the sum of societal knowledge, then you don't go putting petty restrictions on your knowledge.
Sometimes, when you fight fire with fire, all you get is a bigger fire and you certainly don't put out a fire by loudly exclaiming that water is the new fire.
Footnotes
1 - Okay, I'm kidding about the last one.
2 - Well, that's not completely true. I also don't release code that I know is bad because I don't want people copying or learning from code I know has serious problems.
Rabu, 08 Juli 2009
Core Plot
I just learned about an open source graphing library for the iPhone called Core Plot.

Looks like it's got a lot of potential, and I know a lot of people have asked about graphic libraries, so there you go.
via Michael Fey

Looks like it's got a lot of potential, and I know a lot of people have asked about graphic libraries, so there you go.
via Michael Fey
Selasa, 19 Mei 2009
Device Detection
Update: The author of the device detection code has been identified! Max Horváth dropped me a note letting me know that this lovely little bit of code was written by him. He's got a great blog that often covers iPhone SDK material also.Somebody asked me over Twitter for how to detect what device the code was running on. Since a tree fell in my backyard the other day, right on the telephone lines and taking out my internet service in the process, I was working on an iPhone, and trying to answer a question quickly.
In short, I gave a wrong answer. My apologies to anybody who relied on it.
Here's some code, written by Max Horváth, that detects the device model correctly.
#import <sys/utsname.h>
enum {
MODEL_IPHONE_SIMULATOR,
MODEL_IPOD_TOUCH,
MODEL_IPHONE,
MODEL_IPHONE_3G
};
@interface DeviceDetection : NSObject
+ (uint) detectDevice;
+ (NSString *) returnDeviceName:(BOOL)ignoreSimulator;
@end
@implementation DeviceDetection
+ (uint) detectDevice {
NSString *model= [[UIDevice currentDevice] model];
// Some iPod Touch return "iPod Touch", others just "iPod"
NSString *iPodTouch = @"iPod Touch";
NSString *iPodTouchLowerCase = @"iPod touch";
NSString *iPodTouchShort = @"iPod";
NSString *iPhoneSimulator = @"iPhone Simulator";
uint detected;
if ([model compare:iPhoneSimulator] == NSOrderedSame) {
// iPhone simulator
detected = MODEL_IPHONE_SIMULATOR;
} else if ([model compare:iPodTouch] == NSOrderedSame) {
// iPod Touch
detected = MODEL_IPOD_TOUCH;
} else if ([model compare:iPodTouchLowerCase] == NSOrderedSame) {
// iPod Touch
detected = MODEL_IPOD_TOUCH;
} else if ([model compare:iPodTouchShort] == NSOrderedSame) {
// iPod Touch
detected = MODEL_IPOD_TOUCH;
} else {
// Could be an iPhone V1 or iPhone 3G (model should be "iPhone")
struct utsname u;
// u.machine could be "i386" for the simulator, "iPod1,1" on iPod Touch, "iPhone1,1" on iPhone V1 & "iPhone1,2" on iPhone3G
uname(&u);
if (!strcmp(u.machine, "iPhone1,1")) {
detected = MODEL_IPHONE;
} else {
detected = MODEL_IPHONE_3G;
}
}
return detected;
}
+ (NSString *) returnDeviceName:(BOOL)ignoreSimulator {
NSString *returnValue = @"Unknown";
switch ([DeviceDetection detectDevice]) {
case MODEL_IPHONE_SIMULATOR:
if (ignoreSimulator) {
returnValue = @"iPhone 3G";
} else {
returnValue = @"iPhone Simulator";
}
break;
case MODEL_IPOD_TOUCH:
returnValue = @"iPod Touch";
break;
case MODEL_IPHONE:
returnValue = @"iPhone";
break;
case MODEL_IPHONE_3G:
returnValue = @"iPhone 3G";
break;
default:
break;
}
return returnValue;
}
@end
Sabtu, 04 April 2009
Multi-Row Delete Project in Google Code
I have taken the code project from my earlier blog posting on multi-row deletes in table views and checked it into Google. Code. You can find the project here.
Kamis, 02 April 2009
Zip & Unzip Objective-C Code
A new Google Code Project gives you the ability to zip and unzip data from Objective-C. I haven't used this yet, but definitely plan to check it out.
Selasa, 31 Maret 2009
Speed with a Catch
A while back, I wrote a post about surface normals in OpenGL ES. Yesterday on Twitter, there was some discussion about using the inverse square root function from Quake 3 to speed up the performance of iPhone OpenGL ES applications. Here is what that method looks like (converted to using GL and iPhone data types):
The inverse square root can be used in several ways. Noel Llopis of Snappy Touch pointed out two uses for it on Twitter yesterday: calculating normals and doing spherical UV texture mapping. I'm still trying to wrap my head around the UV Texture Mapping, but I understand normals pretty well at this point, so I though I'd see what kind of performance gains I could get using this old optimization. There's all sorts of arguments around the intertubes about whether this function still gives performance gains, but there's an easy way to find out: use it and measure with Shark.
I used my Wavefront OBJ Loader as a test, and profiled the loading of the most complex of the three objects - the airplane. The first run was using my original code, which stupidly1 used sqrt(). I then re-ran it using sqrtf(), and then again using the Quake3D InvSqrt() function above.
The results were impressive, and you definitely do get a performance increase from using this decade-old function on the iPhone. Using InvSqrt() gave a 15% decrease in time spent calculating surface normals over using sqrtf() and a 40% decrease over calculating with sqrt(). That's not an amount to be sneezed at, especially in situations where you need to calculate normals on the fly many times a second.
Now, if you remember, this was how we calculated normals using the square root function from Math.h:
So... how can we tweak this to use inverse square root? Well, the inverse square root of a number is simply 1 divided by the square root of that number. In Vector3DNormalize(), we divide each of the components of the vector (x,y,and z) by the magnitude of the vector, which is calculated using square root. Since dividing a value by a number is the same as multiplying by 1 divided by that same number, so, we can just multiply each component by the inverse magnitude instead, like so:
Sweet, right? If we now use Vector3DFastNormalize() instead of Vector3DNormalize(), and each call will be about 15% faster on current generations of the iPhone and iPod Touch compared to using the built-in square root function.
But… there's a catch. Actually, two catches.
The first catch is that this optimization doesn't work faster on all hardware. In fact, on some hardware, it is measurably slower than using sqrtf(). That means you're gambling that future hardware will also benefit from this same optimization. Not a huge deal and very possibly a safe bet, but you should be aware of it, and be prepared to back it out quickly should Apple release a new generation of iPhones and iPod Touches that use a different processor.
The second, and far more important catch is the possible legal ramifications of using this code. You see, Id released Quake3D's source code under the GNU Public License, which is a viral license. If you use source code from a GPL project, you have to open source your entire project under the GPL as well. Now, that's an oversimplification, and there are ways around the GPL, but as a general rule, if you use GPL'd code, you have to make your code GPL also.
But, the waters are a little murky. John Carmack has admitted that he didn't write that function, and doesn't think the other programmers at Id did either. The actual author of the code is unknown. Some of the contributors to the function have been found, but not the original author. That means the code MIGHT be in the public domain. If that's the case, its inclusion in a GPL application doesn't take it out of the public domain.
So, bottom line: is it safe to use? Probably. This function is widely known and widely used and there's been no indication that any possible rights owner has any interest in chasing down every use of this function. Are there any guarantees? Nope.
My recommendation is to use it, but make sure every place you use it, have a backup method that you can fallback on if you need to. If you want some assurance, you could try contacting Id legal and getting a waiver to use that function. I don't know if they'll respond, or if they'll grant it, but the folks at Id have always struck me as good people, so it might be worth an inquiry if you're risk averse.
1 - sqrt() is a double-precision function. Since OpenGL ES doesn't support the GLDouble datatype, which means I was doing the calculation on twice as many bits as needed, and converting back and forth from single to double precision then back again.
static inline GLfloat InvSqrt(GLfloat x)
{
GLfloat xhalf = 0.5f * x;
int i = *(int*)&x; // store floating-point bits in integer
i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
x = *(GLfloat*)&i; // convert new bits into float
x = x*(1.5f - xhalf*x*x); // One round of Newton's method
return x;
}The inverse square root can be used in several ways. Noel Llopis of Snappy Touch pointed out two uses for it on Twitter yesterday: calculating normals and doing spherical UV texture mapping. I'm still trying to wrap my head around the UV Texture Mapping, but I understand normals pretty well at this point, so I though I'd see what kind of performance gains I could get using this old optimization. There's all sorts of arguments around the intertubes about whether this function still gives performance gains, but there's an easy way to find out: use it and measure with Shark.
I used my Wavefront OBJ Loader as a test, and profiled the loading of the most complex of the three objects - the airplane. The first run was using my original code, which stupidly1 used sqrt(). I then re-ran it using sqrtf(), and then again using the Quake3D InvSqrt() function above.
The results were impressive, and you definitely do get a performance increase from using this decade-old function on the iPhone. Using InvSqrt() gave a 15% decrease in time spent calculating surface normals over using sqrtf() and a 40% decrease over calculating with sqrt(). That's not an amount to be sneezed at, especially in situations where you need to calculate normals on the fly many times a second.
Now, if you remember, this was how we calculated normals using the square root function from Math.h:
static inline GLfloat Vector3DMagnitude(Vector3D vector)
{
return sqrt((vector.x * vector.x) + (vector.y * vector.y) + (vector.z * vector.z));
}
static inline void Vector3DNormalize(Vector3D *vector)
{
GLfloat vecMag = Vector3DMagnitude(*vector);
if ( vecMag == 0.0 )
{
vector->x = 1.0;
vector->y = 0.0;
vector->z = 0.0;
}
vector->x /= vecMag;
vector->y /= vecMag;
vector->z /= vecMag;
}So... how can we tweak this to use inverse square root? Well, the inverse square root of a number is simply 1 divided by the square root of that number. In Vector3DNormalize(), we divide each of the components of the vector (x,y,and z) by the magnitude of the vector, which is calculated using square root. Since dividing a value by a number is the same as multiplying by 1 divided by that same number, so, we can just multiply each component by the inverse magnitude instead, like so:
static inline GLfloat Vector3DFastInverseMagnitude(Vector3D vector)
{
return InvSqrt((vector.x * vector.x) + (vector.y * vector.y) + (vector.z * vector.z));
}
static inline void Vector3DFastNormalize(Vector3D *vector)
{
GLfloat vecInverseMag = Vector3DFastInverseMagnitude(*vector);
if (vecInverseMag == 0.0)
{
vector->x = 1.0;
vector->y = 0.0;
vector->z = 0.0;
}
vector->x *= vecInverseMag;
vector->y *= vecInverseMag;
vector->z *= vecInverseMag;
}
Sweet, right? If we now use Vector3DFastNormalize() instead of Vector3DNormalize(), and each call will be about 15% faster on current generations of the iPhone and iPod Touch compared to using the built-in square root function.
But… there's a catch. Actually, two catches.
The Catches
The first catch is that this optimization doesn't work faster on all hardware. In fact, on some hardware, it is measurably slower than using sqrtf(). That means you're gambling that future hardware will also benefit from this same optimization. Not a huge deal and very possibly a safe bet, but you should be aware of it, and be prepared to back it out quickly should Apple release a new generation of iPhones and iPod Touches that use a different processor.
The second, and far more important catch is the possible legal ramifications of using this code. You see, Id released Quake3D's source code under the GNU Public License, which is a viral license. If you use source code from a GPL project, you have to open source your entire project under the GPL as well. Now, that's an oversimplification, and there are ways around the GPL, but as a general rule, if you use GPL'd code, you have to make your code GPL also.
But, the waters are a little murky. John Carmack has admitted that he didn't write that function, and doesn't think the other programmers at Id did either. The actual author of the code is unknown. Some of the contributors to the function have been found, but not the original author. That means the code MIGHT be in the public domain. If that's the case, its inclusion in a GPL application doesn't take it out of the public domain.
So, bottom line: is it safe to use? Probably. This function is widely known and widely used and there's been no indication that any possible rights owner has any interest in chasing down every use of this function. Are there any guarantees? Nope.
My recommendation is to use it, but make sure every place you use it, have a backup method that you can fallback on if you need to. If you want some assurance, you could try contacting Id legal and getting a waiver to use that function. I don't know if they'll respond, or if they'll grant it, but the folks at Id have always struck me as good people, so it might be worth an inquiry if you're risk averse.
1 - sqrt() is a double-precision function. Since OpenGL ES doesn't support the GLDouble datatype, which means I was doing the calculation on twice as many bits as needed, and converting back and forth from single to double precision then back again.
17.28
ipod touch review

