• Hi there !

    I'm currently looking for ways to optimise the way curves are drawn on an OLED screen ( & later rounded polygons ;) ).

    By lessenning the number of "steps" used for a curve, I'm getting close to "instantaneous refresh", but I bet there's some way to use "compiled" flag to get even faster calls ( which 'll get handy when drawing more than one curve, for example two rounded polys ).

    I tried rewriting the following functions, but always ended up with either an error ( "ObjectExpression is not implemented yet" or "ArrayExpression is not implemented yet" ).
    When trying "E.compiledC()", it seems there's a limit on the maximum number of args for a function ( 4 arguments if I got it right from the below test code, if more I got a "Error Parsing signature at argument number " )

    Any hint on getting this as fast as can be ? ( I plan to using the above two "tricks" - "compiled" & "E.compiledC" - and also to later drive some strips of APA102 in a POV manner, and this before moving onto creating a "firmware Extension" ( .. ) )

    Thanks in advance ! ;)

    Curves helpers

    function bezierCurve(t, p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y){
      var t2 = t * t;
      var t3 = t2 * t;
      var oneMinT = 1 - t;
      var oneMinT2 = oneMinT * oneMinT;
      var oneMinT3 = oneMinT2 * oneMinT;
    
      return {
        x: p0x * oneMinT3 + 3 * p1x * t * oneMinT2 + 3 * p2x * t2 * oneMinT + p3x * t3,
        y: p0y * oneMinT3 + 3 * p1y * t * oneMinT2 + 3 * p2y * t2 * oneMinT + p3y * t3
      };
    }
    function quadraticCurve(t, p0x, p0y, p1x, p1y, p2x, p2y){
      var t2 = t * t;
      var oneMinT = 1 - t;
      var oneMinT2 = oneMinT * oneMinT;
    
      return {
        x: p0x * oneMinT2 + 2 * p1x * t * oneMinT + p2x *t2,
        y: p0y * oneMinT2 + 2 * p1y * t * oneMinT + p2y *t2
      };
    }
    

    no-that-fast curve drawing

    function drawCurve(){
      var p0 = { x: 20, y: 10};
      var p1 = { x: 20, y: 63};
      var p2 = { x: 127, y: 10};
      var time = 0;
      //var stepping = 0.005; // seems the nicest
      //var stepping = 0.05; // a little less neat, yet faster
      var stepping = 0.1; // quick enough ?
      var pathPts = [];
      for(time = 0; time <= 1; time+= stepping){
        var pos = quadraticCurve(time, p0.x, p0.y, p1.x, p1.y, p2.x, p2.y);
        pathPts.push(pos.x, pos.y);
      }
      g.drawPoly(pathPts, false);
      g.flip();
    }
    

    Max 4 arguments limit ? ( and yes, I put 'int' instead of 'float' to test out .. )

    var c = E.compiledC(`
    // int quadraticCurveCX(int, int , int ,int)
    int quadraticCurveCX(int t, int p0x, int p0y, int p1x){ // maximum 4 args ..
     //int t2 = t*t;
     //int oneMinT = 1-t;
     //int oneMinT2 = oneMinT * oneMinT;
     return 0; //p0x * oneMinT2 + 2 * p1x * t * oneMinT + p2x *t2;
    }
    `);
    

    Chunks of code from last unsuccessful try

    function quadraticCurveCY(t, p0x, p0y, p1x, p1y, p2x, p2y){
      //"compiled";
      var t2 = t*t;
      var oneMinT = 1-t;
      var oneMinT2 = oneMinT * oneMinT;
      //return p0x * oneMinT2 + 2 * p1x * t * oneMinT + p2x *t2;
      return p0y * oneMinT2 + 2 * p1y * t * oneMinT + p2y *t2;
    }
    function getCurvePts(){
      //"compiled";
      var p0x = 20, p0y = 10;
      var p1x = 20, p1y = 63;
      var p2x = 127, p2y =10;
      var time = 0;
      var stepping = 0.005; // seems the nicest
      var pathPts = [];
      for(time = 0; time <= 1; time+= stepping){
        //var pos = quadraticCurveC(time, p0x, p0y, p1x, p1y, p2x, p2y);
        //pathPts.push(pos[0], pos[0]);
        //var posX, posY;
        //var pos = quadraticCurveC(time, p0x, p0y, p1x, p1y, p2x, p2y, posX, posY);
        //pathPts.push(posX, posY);
        //var posX = c.quadraticCurveCX(time, p0x, p0y, p1x, p1y, p2x, p2y);
      }
      return pathPts;
    }
    
    function drawCurve(){
      g.drawPoly(getCurvePts(), false);
      g.flip();
    }
    

    I see if I can find time to learn & try writing my own C extensions today ( right after some test on OLED screen SSD1306: it seems passing a bitrate of 800000 works, but I'm not sure if the difference 'll be visible since I'm not sure of the "resolution*" of 'setInterval/setTimeout' on Espruino).

    *Putting it another way, does Espruino handle <1ms as setInterval/setTimeout arg ?
    ( & If so, how to get such small delay in a reliable manner ? )

    This being said, good weekend everyone ;)
    ++

About

Avatar for stephaneAG @stephaneAG started