Thursday, November 18, 2010

Image editor gets some love

After my breakthrough with the line and bezier drawing, I've decided it's time to nickel and dime a few things.

This evening I spent about 2 hours getting images to auto-snap in place in the pict editor as well as toggling the images on and off.  This will help with drawing pictures as you can now toggle the background images on and off and "trace" them to get a better picture.  I wanted to actually resize the image rather than just displaying it resized, but alas that's not as easy as I expected.  Still not sure why, that's where the bulk of my time has gone.  NSImage expects you to know a lot more about images than I do apparently.

This still needs some work -- you can add as many pictures as you want (we should limit to 1) and the images need to be re-sampled down smaller than they are.  We also need to make a category, phrase (hint?) and exact word match meta-data in the editor as well so that the pict app can do something useful with the sketch files.

I may as well post a picture as an example of the image background scaling, since this blog would be awfully boring without pictures.  Well okay, and maybe a little bit boring WITH pictures.  Please excuse zeratul's arm, it's currently part of my desktop background.  You can see the auto-scaling at work, the regular size is in preview.

Monday, November 15, 2010

pitfalls of early optimization

So I don't know that I've mentioned this on this blog, at least not recently.  Pict has had a serious issue drawing straight lines when run on the iPad.  As in it locks up the whole iPad for seconds at a time while drawing straight lines if they are longer than about an inch.

Drawing lines and curves over time isn't something that's normally done for computer graphics.  Most applications want to draw a line or a curve from start to finish, they aren't interested in the user watching this happen.  Incidentally the math is totally different.  Fortunately I'm building on the shoulders of giants.  Well, people better at math than I am.

I created my own actions in cocos2d by overriding the CCMoveTo and CCBezierTo classes.  In practice this means that I needed one additional piece of information (the last time we've updated) to be able to draw the points we may have missed along the way in addition to using a CCRenderTexture to draw the "pen" sprite into.

This has been a thorn in my side for months and a point of discouragement on this project.  What's the point of making a drawing app if the drawing takes way too long?  Without that the app is dead.  Very discouraging.

I've been hitting my drawing code off and on for the past four months and have made little headway.  This saturday past I sat down for almost 5 hours and gave it a serious rework.  I know WAY more than I want to about bezier paths and drawing a point on a line.  However I ended up giving up around 1 AM.  The one thing I knew at the end of the night was that most of my approaches had been flawed and I knew why.

However my focus was all for naught.  It seems that due to profiling where my time was being spent with instruments, I was misled. Yes, all of my time was spent drawing and that's where things pointed.  The solution was not how often I was calculating or where I was doing my drawing, but how often I drew to the CCRenderTexture.  Specifically how often I called CCRenderTexture's begin and end functions.  Rather than move my CCSprite and using the method [sprite visit], I saved all of my positions and then drew them in a for loop in my render texture.  In pseudo-code the original was doing something like this:

// figure out the new sprite position that's needed to draw
// draw the sprite into the render texture
  // CCRenderTexture begin drawing
  // set the sprite to the new position
  // [sprite visit]
  // CCRenderTexture end drawing
// repeat as necessary
// return out of our update function

After many many attempts at changing how many and often I drew, I changed the code to do this:


// figure out the new sprite position that's needed to draw
// save the new position
// repeat as necessary

// CCRenderTexture begin drawing
// iterate over my points, moving my sprite
  // [sprite visit]
// CCRenderTexture end drawing
// return out of our update function

This totally fixed the problem.  Ugh, what a pain!  In hindsight it seems somewhat obvious.  Maybe I'm clueless but I'd like to think it wasn't obvious from my previous perspective.

Lesson:  CCRenderTexture (and as an extension, some openGL calls) can be expensive if used too often!

Here is a reference to the (old) cocos2d threads related specifically to my drawing are here, here and here.