Announcement

Collapse
No announcement yet.

My technique for anti-aliased animation and bitmaps

Collapse
X
  • Time
  • Show
Clear All
new posts

  • My technique for anti-aliased animation and bitmaps

    Hey everyone.

    I recently built the "Ranger" watchface.
    It's a super-crisp watchface that uses anti-aliasing for every part of the screen, including the moving hands. I thought I'd share with you how this was made possible, using an example that I had developed previously (with the source code too!)


    Drawing Anti-aliased primitives

    As we know, drawing native polygons and lines are not anti-aliased. I actually built a little library that draws AA lines, and simple AA polygons — check out the code, and the screenshot;
    https://github.com/sunpazed/garmin-drawaa

    However, there's not enough processor time on the watch to draw lots of primitives with this method. Period. So we need another method.


    Using lots of Bitmaps

    Another option is to use many bitmaps. With 60 frames of animation and at most a 240x240 resolution screen, this quickly becomes an issue with size of the packaged app — up to 1.5Mb of storage! Also, it doesn't solve the anti-aliasing issue, as CIQ does not support bitmaps with an alpha channel (only a single transparent "colour").


    Font-based tilemaps

    I developed games back in the days of 8-bit systems. It was very common for these systems to use fonts or tilemaps to optimally represent large chunks of bitmapped data. Given CIQs small footprint and font-based features, I thought I'd try my luck replicating this technique.

    Not only is this is a more storage-friendly method than Bitmaps, it allows developers to efficiently pack many frames of bitmapped animation in a ~26kb font. Also, the great thing about fonts, its that they do alpha blending with the existing framebuffer on the canvas. So, you get anti-aliasing as a nice by-product.

    As an example to showcase this method, I thought I'd replicate a featured watchface from our fruity competitor;


    As Mickey's hands have quite a bit of detail, they're represented as a bitmap which is rotated 60 times. Here's how each frame of Mickey's hands are represented as a tile-map;


    To encode this tilemap data, there's an array that maps each tile to a position on the screen. From a memory perspective, this is stored as a 32-bit signed integer which has been bit-packed with 4 bytes to be more efficient.

    Code:
    const hands = [
            [23068672,41418752,56629248,74979328,90189824,108539904,123750400,140533760],
            [158859264,174069760,192419840,207630336,225980416,241190912,259540992,274751488,293101568],
            ...
    Drawing each bitmapped frame on the device is now really simple. All we need to do is decode the array, and draw some text;

    Code:
    for (var i = 0; i < hands.size(); i++)
      {
        var packed_value = hands[i];
    
        var pad = packed_value & 255;
        packed_value >>= 8;
        var ypos = packed_value & 255;
        packed_value >>= 8;
        var xpos = packed_value & 255;
        packed_value >>= 8;
        var char = packed_value & 255;
    
        dc.drawText(xpos.toNumber(),ypos.toNumber(),font,char.toNumber().toChar(),Gfx.TEXT_JUSTIFY_LEFT);
      }
    The result is a bitmap drawn on the screen (in any colour we want), and perfectly alpha-blended with the frambuffer.

    And that's pretty much it. Now, I know this technique isn't for everyone, and yes, it has drawbacks (can only draw flat colours) — but for the benefit of the developer community, I believe it's an interesting technique to showcase.

    To generate the tilemap, font, and tilemap array — I've built my own custom tool. Once I clean it up, I'll release the source so that other developers can use this technique.

    If you're interested in compiling your own version of Mickey (it's not on the app store) — check out the source code here;

    https://github.com/sunpazed/garmin-mickey

    Oh, and remember, I'm releasing this source in good faith. So no rip-off's in the app store please (you know who you are).

    Happy to hear your thoughts. Cheers.
    Attached Files
    Last edited by ftrimboli; 04-11-2017, 08:51 PM. Reason: typos ..

  • #2
    B.R.A.V.O !!

    I love seeing this kind of old-school optimization and workarounds.
    Current Fenix5X + Tempe + Foot Pod
    Previous Fenix2, Fenix3 : SN 46300xxxx

    My apps

    Comment


    • #3
      is it because of Disney copyright issues you don't release it to the app store?
      My best Connect IQ apps:Other:

      Comment


      • #4
        Very cool!
        What about a version with the conneciq monkey?

        Comment


        • #5
          Thanks folks.

          Yes, I guess the situation is complicated as Mickey is an exclusive on another device. But the reality is, I really wanted an analogue watch example with embellished hands that I was happy to open source — so no love lost.

          Stanislav already did a great job of the "MonkeyC" mascot, check it out in the app store.

          Comment


          • #6
            So how to prepare so many hand graphics, and how to map them in coordinate positions array?

            Comment


            • #7
              Originally posted by sis651 View Post
              So how to prepare so many hand graphics, and how to map them in coordinate positions array?
              I built a small tool...



              It automatically generates the tile image, the .fnt definition, and the array. A few steps are still manual. I'm still working on it to make it user friendly — so that you can upload an image or vector file, process it, and then download a zip will all the components.
              Attached Files

              Comment


              • #8
                Originally posted by ftrimboli View Post
                I built a small tool...



                It automatically generates the tile image, the .fnt definition, and the array. A few steps are still manual. I'm still working on it to make it user friendly — so that you can upload an image or vector file, process it, and then download a zip will all the components.
                Great work ftromboli ! I suppose you didn't release Ranger watchface on fenix3 because not enough horse power or because of too scarse color palette ?

                Comment


                • #9
                  tool availability

                  Hi,

                  I was wondering if you were still thinking about sharing the tool to generate the hands? I just gave another try to create a analog watch face but in my opinion, the hands look horrible when drawing them on the device
                  ex: https://apps.garmin.com/en-CA/apps/2...1-6620bb5c8615

                  I also believe that this could be a great addition for all developers and could really boost the quality of analog watch faces in general. Even more, Gamin should consider adding it in the developer blog like what they did with the fonts ( https://developer.garmin.com/index.p...m-fonts-tricks )

                  Cheers

                  Comment


                  • #10
                    This is brilliant

                    Are you able to share the tool yet? I can't wait to give it a try.

                    Cheers

                    Comment


                    • #11
                      Can't wait to give it a try.

                      Comment


                      • #12
                        This is great! I'm new to CIQ, but not to programming. I used the font overwriting with a Commodore VIC20 back 1983. This will be fun to try! Thank you for sharing.

                        Comment


                        • #13
                          Franco does interesting things, that's for sure! Check out his stuff in the app store!

                          Also, when it comes to "interesting things" you can do with custom fonts, you may want to check out HermoT's post in the developer blog
                          My Connect IQ Apps in the Store
                          Facebook - Instagram -
                          Twitter

                          Comment

                          Working...
                          X