How do I make a number go from 0 to 255 and back down again without using "if" statements?

GavGav
edited October 2017 in How To...

Hello,

I would like to make a variable go up to a max number by a certain increment each time and then make it go back down to 0 by the same increment, and repeat. variable % maxNumber just floors the number at 0. I would like the number to be maxNumber - (variable % maxNumber) after variable > maxNumber until variable > maxNumber * 2, then I just want variable to be floored again to start the process over. I could use a "sin" function, but I don't like the way it curves. I also would rather not use "if" or "while" statements because it feels like cheating. I'm complicating this too much in my head, does anybody know how to do this?

Any help would be appreciated, thanks!

-Gav

Answers

  • int n;
    
    void setup() {
      frameRate(20);
    }
    
    void draw() {
      print(n + " - ");
      n = (n+1) % 256;
    }
    
  • Hey, thanks for the answer! I seem to have miscommunicated my question. That code you gave me floors the number at 0 every time it hits 256. Is there a way to make the number start descending once it gets to the max instead of flooring it?

  • int n, inc = 1;
    
    void setup() {
      frameRate(20);
    }
    
    void draw() {
      print(n + " - ");
      n += inc;
      inc *= (n & 0xff) == 0? -1 : 1;
    }
    
  • Does it have to be completely logic free? GoToLoop's example uses the ternary conditional operator, which acts like a mini if statement for assigning a value to a variable, which is good but may be what you were asking not to include.

  • Damnit. I give up.

    int n;
    
    void setup() {
      frameRate(20);
    }
    
    void draw() {
      n = (256-abs(((frameCount)%512)-256));
      print(n + " - ");
    }
    
  • edited October 2017
    float n;
    float increment = PI;
    
    void setup() {
     frameRate(20); 
    }
    
    void draw() {
     increment += PI / 12; 
     n = map(cos(increment), -1, 1, 0, 255);
     println(n);
     }
    

    Here's my implementation using cosine :P I know you didn't want to use it so I'll think of something else. Perhaps some Calculus could get this done?

  • branchless fx

    • blue: sin
    • green: linear
    • red: smoothstep-linear

    diewald_fx

    
    public void settings(){
      size(900,150);
      smooth(8);
    }
    
    public void setup(){
      background(32);
    }
    
    public void draw(){
      plot(frameCount);
      plot(mouseX);
    }
    
    public void plot(int x){
      int wh = 4;
      int HI = height;
      
      noStroke();
      rectMode(CENTER);
      
      {
        float y = fxSin(x, HI);
        fill(0,128,255);
        ellipse(x, y, wh, wh);
      }
      
      {
        int y = fxLin(x, HI);
        fill(0,255,0);
        ellipse(x, y, wh, wh);
      }
    
      {
        float y = fxLin(x, HI);
        y = fxSmoothstep(y/HI, HI);
        // y = fxSmootherstep(y/HI, HI);
        fill(255,64,0);
        ellipse(x, y, wh, wh);
      }
    }
    
    
    public int fxLin(int x, int hi){
      int i = x / hi;     //  0, 1, 2, ....
      int f = x - hi * i; //  modulo
      int p = i & 1;      //  0 or +1
      int d = p * 2 - 1;  // -1 or +1
      int y = p * hi - d * f;
      return y; 
    }
    
    public float fxSin(float x, float hi){
      float shift = -PI * 0.5f;
      float freq = x * PI / hi + shift;
      float y = (sin(freq) * 0.5f + 0.5f) * hi;
      return y; 
    }
    
    
    public float fxSmoothstep(float x, float hi){
      // en.wikipedia.org/wiki/Smoothstep
      // www.khronos.org/registry/OpenGL-Refpages/gl4/html/smoothstep.xhtml
      float y = x*x*(3 - 2*x);
      return y * hi; 
    }
    
    public float fxSmootherstep(float x, float hi){
      float y = x*x*x*(x*(x*6 - 15) + 10);
      return y * hi; 
    }
      
    
  • Holy jesus nice example T_D!

    ... I hope we can all appreciate if statements a little bit more.

  • edited October 2017

    smooth(8);

    • According to https://Processing.org/reference/smooth_.html
    • There are only 2 smoothing values available for renderer JAVA2D: 2 & 3.
    • 2 is bilinear and 3 is bicubic smoothing.
    • Notice that 3, which is the best smoothing algorithm for the default renderer JAVA2D, is already the default smoothing value btW. :>
  • T_DT_D
    edited October 2017

    A more generic version that works for floats and negative values too.

    
    public void settings(){
      size(900,150);
    }
    
    public void setup(){
      background(32);
      noStroke();
    }
    
    public void draw(){
      float tx = -width/2;
      float dh = height;
      translate(-tx,0);
      
      plot(frameCount+tx, dh);
      plot(mouseX    +tx, dh);
    }
    
    public void plot(float x, float dh){;
      float y;
    
      y = fxSin(x / dh - 0.5f) * dh;
      fill(0,128,255);
      ellipse(x, y, 2, 2);
    
      y = fxLin(x / dh) * dh;
      fill(0,255,0);
      ellipse(x, y, 2, 2);
    
      y = fxSmootherstep(fxLin(x / dh)) * dh;
      fill(255,64,0);
      ellipse(x, y, 2, 2);
    }
    
    public float fxLin(float x){
      int   i = floor(x);   //  0, 1, 2, 3, ...
      float f = x - i;      //  fract(x)
      int   p = i & 1;      //  0, 1, 0, 1, ...
      int   d = -p * 2 + 1; // +1,-1,+1,-1, ...
      return p + d * f;
    }
    
    public float fxSin(float x){
      return sin(PI * x) * 0.5f + 0.5f;
    }
    
    // en.wikipedia.org/wiki/Smoothstep
    // www.khronos.org/registry/OpenGL-Refpages/gl4/html/smoothstep.xhtml
    public float fxSmoothstep(float x){
      return x*x*(3 - 2*x);
    }
    
    public float fxSmootherstep(float x){
      return x*x*x*(x*(x*6 - 15) + 10);
    }
    
    
Sign In or Register to comment.