Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

  • Send individual msj to a shader

    hey everybody. this time i've a problem sending invididual mensajes to a fragment shader. I've an array of spheres, and i want that every sphere have a different size of blur, witch is a uniform of the fragment. The main code is from an example, a post-processing effects.

    How can i do?

    import controlP5.*;
    
    ControlP5 cp5;
    import peasy.*;
    
    ArrayList<Sphere>s;
    
    PGraphics canvas;
    
    PGraphics brightPass;
    PGraphics horizontalBlurPass;
    PGraphics verticalBlurPass;
    
    PShader bloomFilter;
    PShader blurFilter;
    PeasyCam cam;
    float angle = 0;
    
    final int surfaceWidth = 250;
    final int surfaceHeight = 250;
    
    float luminanceFilter = 0.02;
    float blurSize = 100;
    float sigma = 200;
    
    void setup()
    {
      cam = new PeasyCam(this, 1400);
      size(1000, 1000, P3D);
    
      s = new ArrayList<Sphere>();
    
      canvas = createGraphics(width, height, P3D);
    
      brightPass = createGraphics(width, height, P2D);
      brightPass.noSmooth();
    
      horizontalBlurPass = createGraphics(width, height, P2D);
      horizontalBlurPass.noSmooth(); 
    
      verticalBlurPass = createGraphics(width, height, P2D);
      verticalBlurPass.noSmooth(); 
    
      bloomFilter = loadShader("bloomFrag.glsl");
      blurFilter = loadShader("blurFrag.glsl");
    }
    
    void draw()
    {
      background(0);
      bloomFilter.set("brightPassThreshold", luminanceFilter);
      angle += 0.05;
    
      for(Sphere s: s){
      blurFilter.set("blurSize", s.p);
      }
    
      blurFilter.set("sigma", sigma); 
    
      canvas.beginDraw();
      render(canvas);
      canvas.endDraw();
    
      // bright pass
      brightPass.beginDraw();
      brightPass.shader(bloomFilter);
      brightPass.image(canvas, 0, 0);
      brightPass.endDraw();
    
      // blur horizontal pass
      horizontalBlurPass.beginDraw();
      blurFilter.set("horizontalPass", 1);
      horizontalBlurPass.shader(blurFilter);
      horizontalBlurPass.image(brightPass, 0, 0);
      horizontalBlurPass.endDraw();
    
      // blur vertical pass
      verticalBlurPass.beginDraw();
      blurFilter.set("horizontalPass", 0);
      verticalBlurPass.shader(blurFilter);
      verticalBlurPass.image(horizontalBlurPass, 0, 0);
      verticalBlurPass.endDraw();
    
    
      cam.beginHUD();
      blendMode(BLEND);
      blendMode(SCREEN);
      image(brightPass, 0, 0);
      image(verticalBlurPass, 0, 0);
    
      cam.endHUD();
    
    println(frameRate);
    }
    
    void render(PGraphics pg)
    {
      cam.getState().apply(pg);
    
      pg.background(0, 50);
    
      canvas.pushMatrix();
      canvas.translate(width/2, height/2);
      for(Sphere s: s){
      s.display();
    
      }
      canvas.popMatrix();
    
    
    }
    
    void mousePressed() {
      s.add(new Sphere(random(-width/2, width/2), random(-height/2, height/2), random(1000)));
    }
    
    
    class Sphere {
    
      float p;
      float w;
      float h;
    
      Sphere(float _w, float _h, float _p) {
      p = _p;
      w = _w;
      h = _h;
      }
    
      void display() {
        canvas.pushMatrix();
        canvas.translate(w, h);
        noFill();
        canvas.sphere(100);
    
        canvas.popMatrix();
      }
    }
    
  • Converting Java code to Python

    Here's my Python Mode attempt. However, it's not working yet, it's just pitch black! :-&

    This statement crashes the sketch: geombuffer.update(pg_render) within resizeScreen(). Even when following exactly what it does, it doesn't seem to render anything. :o3

    https://GitHub.com/diwi/PixelFlow/blob/master/src/com/thomasdiewald/pixelflow/java/render/skylight/DwScreenSpaceGeometryBuffer.java#L67-L79

    public void update(PGraphics3D pg_src){
      
      resize(pg_src.width, pg_src.height);
      
      pg_geom.beginDraw();
      updateMatrices(pg_src);
      pg_geom.blendMode(PConstants.REPLACE);
      pg_geom.clear();
      pg_geom.shader(shader);
      pg_geom.noStroke();
      scene_display.display(pg_geom);
      pg_geom.endDraw();
    }
    

    So I'm at loss about it! Sorry. X_X Try finding help on diwi or jdf. ^#(^

    """
     * Depth of Field (DoF) (1.20)
     * Thomas Diewald (diwi) (2017-Oct-07)
     
     * GitHub.com/diwi/PixelFlow/blob/master/examples/Miscellaneous/
     * DepthOfField_Demo/DepthOfField_Demo.java
     
     * Refactor by GoToLoop (v1.4.2) (2018-May-18) (PDE v3.3.5)
     * Forum.Processing.org/two/discussion/27905/
     * converting-java-code-to-python#Item_20
    """
    
    add_library('PixelFlow')
    add_library('peasycam')
    
    from com.jogamp.opengl import GL2
    from processing.opengl import PGL
    
    from java.util import Formatter, Locale
    from jarray import zeros
    
    formatter = Formatter(Locale.ENGLISH)
    
    POSITION = 'position: (%8.2f, %8.2f, %8.2f)\n'
    ROTATION = 'rotation: (%8.2f, %8.2f, %8.2f)\n'
    LOOK__AT = 'look-at:  (%8.2f, %8.2f, %8.2f)\n'
    DISTANCE = 'distance: (%8.2f)\n'
    
    TITLE = __file__[:-5] + '   [fps %6.2f]'
    
    BB_SIZE = 800
    BB_OFFSET = BB_SIZE >> 2
    BB_TOTAL = BB_SIZE + BB_OFFSET
    BB_COORD, BB_DIAM = -BB_TOTAL, BB_TOTAL << 1
    
    XMIN, XMAX = -BB_SIZE, BB_SIZE
    YMIN, YMAX = -BB_SIZE, BB_SIZE
    ZMIN, ZMAX = 0, BB_SIZE
    
    BOX_DIAM = BB_OFFSET + BB_OFFSET/20
    SPH_MIN_D, SPH_MAX_D = BB_OFFSET >> 2, BB_OFFSET >> 1
    
    BOXES, SPHERES = 50, 50
    BOX_RANGE, SPH_RANGE = tuple(range(BOXES)), tuple(range(SPHERES))
    
    CROSS_S, ZFAR = 10, 6000
    MULT_BLUR, FPS = 30, 60
    BLUR_POW, RAD60 = pow(MULT_BLUR, 1/3.0), 60*DEG_TO_RAD
    
    BASE_COL, CROSS_COL = 0x80FFFFFF, 0xd0FFFFFF
    
    SEED, FIXED_SEED = 0, False
    FULLSCREEN, RESIZABLE = False, False
    apply_dof, alt_render = False, False
    
    resized = zeros(1, 'z')
    cube_smooth, cube_facets = DwCube(4), DwCube(2)
    shp_scene = pg_render = pg_dof = pg_tmp = None
    
    def settings():
        if FULLSCREEN: fullScreen(P3D) 
        else: size(this.displayWidth*9/10, this.displayHeight*9/10, P3D)
        noSmooth()
    
    
    def setup():
        frameRate(FPS); cursor(CROSS)
    
        global surf, canv
        surf, canv = this.surface, this.graphics
    
        if RESIZABLE: surf.resizable = True
        surf.setLocation(this.displayWidth - width >> 1, 8)
    
        global peasy
        peasy = PeasyCam(this, -4.083, -6.096, 7, 2000)
        peasy.setRotations(1.085, -.477, 2.91)
    
        global context, dw_filter, dof, param, geombuffer, magnifier
    
        context = DwPixelFlow(this)
        dw_filter = DwFilter.get(context)
        context.print(); context.printGL()
    
        dof = DepthOfField(context)
        param = dof.param
        param.mult_blur = MULT_BLUR
    
        class SceneDisplay(DwSceneDisplay):
            def display(_, canvas): displayScene(canvas)
    
    
        geombuffer = DwScreenSpaceGeometryBuffer(context, SceneDisplay())
    
        mag_h = height/3
        magnifier = DwMagnifier(this, 4, 0, height - mag_h, mag_h, mag_h)
    
    
    def draw():
        setTitle(); resizeScreen(); displaySceneWrap(pg_render)
        dw_filter.gamma.apply(pg_render, pg_render)
    
        apply_dof and applyDoF()
        renderScene()
    
    
    def keyPressed():
        global apply_dof, alt_render, shp_scene
        k = chr(keyCode) if key != CODED else keyCode
    
        if k == 'P' or k == BACKSPACE: noLoop() if this.looping else loop()
        elif k == 'C' or k == CONTROL: printCam()
        elif k == ' ': apply_dof ^= True
        elif k == SHIFT: alt_render ^= True
        elif k == ENTER or k == RETURN: shp_scene = None
    
    
    def applyDoF():
        geom = geombuffer.pg_geom
        dw_filter.gaussblur.apply(geom, geom, pg_tmp, BLUR_POW)
    
        param.focus_pos[0] = map(mouseX + .5, 0, width, 00, 1)
        param.focus_pos[1] = map(mouseY + .5, 0, height, 1, 0)
        dof.apply(pg_render, pg_dof, geombuffer)
    
        dw_filter.copy.apply(pg_dof, pg_render)
    
    
    def renderScene():
        pg = geombuffer.pg_geom if alt_render else pg_render
    
        magnifier.apply(pg, mouseX, mouseY)
        magnifier.displayTool()
    
        DwUtils.beginScreen2D(canv)
        # peasy.beginHUD()
    
        blendMode(REPLACE); image(pg, 0, 0)
        magnifier.display(pg, 0, height - magnifier.h)
    
        fpx = param.focus_pos[0] * width
        fpy = (1 - param.focus_pos[1]) * height
    
        blendMode(EXCLUSION); strokeCap(PROJECT); stroke(CROSS_COL)
        line(fpx - CROSS_S, fpy, fpx + CROSS_S, fpy)
        line(fpx, fpy - CROSS_S, fpx, fpy + CROSS_S)
        blendMode(BLEND)
    
        # peasy.endHUD()
        DwUtils.endScreen2D(canv)
    
    
    def resizeScreen():
        global pg_render, pg_dof, pg_tmp
        w = width; h = height
    
        perspective(RAD60, float(w)/h, 2, ZFAR)
        peasy.feed()
    
        happened = resized[0] = False
        pg_render = DwUtils.changeTextureSize(this, pg_render, w, h, 8, resized)
        happened |= resized[0]
    
        resized[0] = False
        pg_dof = DwUtils.changeTextureSize(this, pg_dof, w, h, 0, resized)
        happened |= resized[0]
    
        resized[0] = False
        pg_tmp = DwUtils.changeTextureSize(this, pg_tmp, w, h, 0, resized,
        GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT)
    
        # geombuffer.update(pg_render)
    
        happened |= geombuffer.resize(pg_render.width, pg_render.height)
        geombuffer.pg_geom.beginDraw()
    
        # geombuffer.updateMatrices(pg_render)
        DwUtils.copyMatrices(pg_render, geombuffer.pg_geom)
    
        geombuffer.pg_geom.blendMode(REPLACE)
        geombuffer.pg_geom.clear()
        geombuffer.pg_geom.shader(geombuffer.shader)
        geombuffer.pg_geom.noStroke()
        geombuffer.scene_display.display(geombuffer.pg_geom)
        geombuffer.pg_geom.endDraw()
    
        return happened | resized[0]
    
    
    def displaySceneWrap(canvas):
        DwUtils.copyMatrices(canv, canvas)
        canvas.beginDraw()
        canvas.background(2)
        displayScene(canvas)
        canvas.endDraw()
    
    
    def displayScene(canvas):
        canvas.directionalLight(255, 255, 255, 200, 600, 400)
        canvas.directionalLight(255, 255, 255, -200, -600, -400)
        canvas.ambientLight(64, 64, 64)
    
        if canvas is geombuffer.pg_geom:
            canvas.background(-1)
            canvas.pgl.clearColor(1, 1, 1, ZFAR)
            canvas.pgl.clear(PGL.COLOR_BUFFER_BIT)
    
        global shp_scene
        if not shp_scene: shp_scene = makeShape()
        canvas.shape(shp_scene)
    
    
    def makeShape():
        scene = createShape(GROUP)
        FIXED_SEED and randomSeed(SEED)
    
        with pushStyle():
            colorMode(HSB, 360, 1, 1); noStroke()
    
            for i in BOX_RANGE:
                px = random(XMIN, XMAX); py = random(YMIN, YMAX)
                sx = random(BOX_DIAM, BOX_DIAM); sy = random(BOX_DIAM, BOX_DIAM)
                sz = random(ZMIN, ZMAX)
    
                fill(random(-45, 45), 1, random(.1, 1))
                shp_box = createShape(BOX, sx, sy, sz)
                shp_box.translate(px, py, sz*.5)
                scene.addChild(shp_box)
    
            for i in SPH_RANGE:
                px = random(XMIN, XMAX); py = random(YMIN, YMAX)
                pz = random(ZMIN, ZMAX); rr = random(SPH_MIN_D, SPH_MAX_D)
    
                fill(random(205, 245), 1, random(.1, 1))
                shp_sphere = createShape(PShape.GEOMETRY)
                shp_sphere.scale(rr); shp_sphere.translate(px, py, pz)
                scene.addChild(shp_sphere)
    
                DwMeshUtils.createPolyhedronShape(shp_sphere, cube_smooth, 1, 4, True)\
                if i&1 else\
                DwMeshUtils.createPolyhedronShape(shp_sphere, cube_facets, 1, 4, False)
    
            fill(BASE_COL)
            scene.addChild(createShape(RECT, BB_COORD, BB_COORD, BB_DIAM, BB_DIAM))
    
        return scene
    
    
    def clearFormatter(f): f.out().setLength(0)
    
    
    def setTitle():
        clearFormatter(formatter)
        surf.title = formatter.format(TITLE, frameRate).toString()
    
    
    def printCam():
        pos = peasy.position; rot = peasy.rotations
        lat = peasy.getLookAt(); dis = peasy.distance
    
        clearFormatter(formatter)
    
        print formatter.\
        format(POSITION, *pos).format(ROTATION, *rot).\
        format(LOOK__AT, *lat).format(DISTANCE, dis)
    
  • Converting Java code to Python

    Hi @solub! It took a long time, but I've just finished refactoring "Depth_of_Field.pde". #:-S

    Now that I've reorganized this sketch, I'm ready to convert it to a ".pyde" file. :)>-

    Just w8 a lil' more. Stay w/ the latest ".pde" file for now: :-\"

    /**
     * Depth of Field (DoF) (1.20)
     * Thomas Diewald (diwi) (2017-Oct-07)
    
     * GitHub.com/diwi/PixelFlow/blob/master/examples/Miscellaneous/
     * DepthOfField_Demo/DepthOfField_Demo.java
    
     * Refactor by GoToLoop (v1.4.2) (2018-May-18) (PDE v3.3.5)
     * Forum.Processing.org/two/discussion/27905/converting-java-code-to-python#Item_18
     */
    
    import com.thomasdiewald.pixelflow.java.DwPixelFlow;
    import com.thomasdiewald.pixelflow.java.geometry.DwIndexedFaceSetAble;
    import com.thomasdiewald.pixelflow.java.geometry.DwCube;
    import com.thomasdiewald.pixelflow.java.geometry.DwMeshUtils;
    import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DepthOfField;
    import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DwFilter;
    import com.thomasdiewald.pixelflow.java.render.skylight.DwSceneDisplay;
    import com.thomasdiewald.pixelflow.java.render.skylight.DwScreenSpaceGeometryBuffer;
    import com.thomasdiewald.pixelflow.java.utils.DwMagnifier;
    import com.thomasdiewald.pixelflow.java.utils.DwUtils;
    
    import peasy.PeasyCam;
    
    import com.jogamp.opengl.GL2;
    
    import static java.util.Locale.ENGLISH;
    import java.util.Formatter;
    
    final Formatter formatter = new Formatter(ENGLISH);
    
    static final String POSITION = "position: (%8.2f, %8.2f, %8.2f)\n";
    static final String ROTATION = "rotation: (%8.2f, %8.2f, %8.2f)\n";
    static final String LOOK__AT = "look-at:  (%8.2f, %8.2f, %8.2f)\n";
    static final String DISTANCE = "distance: (%8.2f)\n";
    
    final String TITLE = getClass().getName() + "   [fps %6.2f]";
    
    static final int BB_SIZE = 800, BB_OFFSET = BB_SIZE >> 2;
    static final int BB_TOTAL = BB_SIZE + BB_OFFSET;
    static final int BB_COORD = -BB_TOTAL, BB_DIAM = BB_TOTAL << 1;
    
    static final int XMIN = -BB_SIZE, XMAX = BB_SIZE;
    static final int YMIN = -BB_SIZE, YMAX = BB_SIZE;
    static final int ZMIN = 0, ZMAX = BB_SIZE;
    
    static final int BOX_DIAM = BB_OFFSET + BB_OFFSET/20;
    static final int SPH_MIN_D = BB_OFFSET >> 2, SPH_MAX_D = BB_OFFSET >> 1;
    
    static final int BOXES = 50, SPHERES = 50;
    
    static final int CROSS_S = 10, ZFAR = 6000;
    static final int MULT_BLUR = 30, BLUR_POW = (int) pow(MULT_BLUR, 1/3.0);
    static final float RAD60 = 60*DEG_TO_RAD, FPS = 60;
    
    static final color BASE_COL = 0x80FFFFFF, CROSS_COL = 0xd0FFFFFF;
    
    static final long SEED = 0;
    static final boolean FIXED_SEED = false;
    
    static final boolean FULLSCREEN = false, RESIZABLE = false;
    boolean apply_dof = false, alt_render = false;
    
    final boolean[] resized = new boolean[1];
    
    final DwIndexedFaceSetAble cube_smooth = new DwCube(4), cube_facets = new DwCube(2);
    
    PGraphics3D pg_render, pg_dof, pg_tmp;
    PShape shp_scene;
    
    PeasyCam peasy;
    
    DwPixelFlow context;
    DwFilter dw_filter;
    DepthOfField dof;
    DwScreenSpaceGeometryBuffer geombuffer;
    DwMagnifier magnifier;
    
    void settings() {
      if (FULLSCREEN) fullScreen(P3D);
      else size(displayWidth*9/10, displayHeight*9/10, P3D);
      noSmooth();
    }
    
    void setup() {
      frameRate(FPS);
      cursor(CROSS);
    
      if (RESIZABLE)  getSurface().setResizable(true);
      getSurface().setLocation(displayWidth - width >> 1, 8);
    
      peasy = new PeasyCam(this, -4.083, -6.096, 7, 2000);
      peasy.setRotations(1.085, -.477, 2.91);
    
      dw_filter = DwFilter.get(context = new DwPixelFlow(this));
      context.print();
      context.printGL();
    
      dof = new DepthOfField(context);
      dof.param.mult_blur = MULT_BLUR;
    
      final DwSceneDisplay scene_display = new DwSceneDisplay() {  
        @ Override final public void display(final PGraphics3D canvas) {
          displayScene(canvas);
        }
      };
    
      geombuffer = new DwScreenSpaceGeometryBuffer(context, scene_display);
    
      final int mag_h = height/3;
      magnifier = new DwMagnifier(this, 4, 0, height - mag_h, mag_h, mag_h);
    }
    
    void draw() {
      final PGraphics canv = getGraphics();
      final DepthOfField.Param param = dof.param;
    
      setTitle();
      resizeScreen();
      displaySceneWrap(pg_render, canv);
      dw_filter.gamma.apply(pg_render, pg_render);
    
      if (apply_dof)  applyDoF(param);
      renderScene(param, canv);
    }
    
    void keyPressed() {
      final int k = keyCode;
    
      if (k == ENTER | k == RETURN)  shp_scene = null;
      else if (k == 'C' | k == CONTROL)  printCam();
      else if (k == 'P' | k == BACKSPACE)  looping ^= true;
      else if (k == ' ')  apply_dof ^= true;
      else if (k == SHIFT)  alt_render ^= true;
    }
    
    void applyDoF(final DepthOfField.Param param) {
      final PGraphicsOpenGL geom = geombuffer.pg_geom;
      dw_filter.gaussblur.apply(geom, geom, pg_tmp, BLUR_POW);
    
      param.focus_pos[0] = map(mouseX + .5, 0, width, 00, 1);
      param.focus_pos[1] = map(mouseY + .5, 0, height, 1, 0);
      dof.apply(pg_render, pg_dof, geombuffer);
    
      dw_filter.copy.apply(pg_dof, pg_render);
    }
    
    void renderScene(final DepthOfField.Param param, final PGraphics canv) {
      final PGraphics pg = alt_render? geombuffer.pg_geom : pg_render;
    
      magnifier.apply(pg, mouseX, mouseY);
      magnifier.displayTool();
    
      DwUtils.beginScreen2D(canv);
      //peasy.beginHUD();
    
      blendMode(REPLACE);
      image(pg, 0, 0);
      magnifier.display(pg, 0, height - magnifier.h);
    
      final float fpx = param.focus_pos[0] * width;
      final float fpy = (1 - param.focus_pos[1]) * height;
    
      blendMode(EXCLUSION);
      strokeCap(PROJECT);
      stroke(CROSS_COL);
      line(fpx - CROSS_S, fpy, fpx + CROSS_S, fpy);
      line(fpx, fpy - CROSS_S, fpx, fpy + CROSS_S);
      blendMode(BLEND);
    
      //peasy.endHUD();
      DwUtils.endScreen2D(canv);
    }
    
    boolean resizeScreen() { // dynamically resize render-targets
      final int w = width, h = height;
    
      perspective(RAD60, (float) w/h, 2, ZFAR);
      peasy.feed();
    
      boolean happened = resized[0] = false;
      pg_render = DwUtils.changeTextureSize(this, pg_render, w, h, 8, resized);
      happened |= resized[0];
    
      resized[0] = false;
      pg_dof = DwUtils.changeTextureSize(this, pg_dof, w, h, 0, resized);
      happened |= resized[0];
    
      resized[0] = false;
      pg_tmp = DwUtils.changeTextureSize(this, pg_tmp, w, h, 0, resized, 
        GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT);
    
      geombuffer.update(pg_render);
      return happened | resized[0];
    }
    
    void displaySceneWrap(final PGraphics3D canvas, final PGraphics canv) {
      DwUtils.copyMatrices((PGraphicsOpenGL) canv, canvas);
      canvas.beginDraw();
      canvas.background(2);
      displayScene(canvas);
      canvas.endDraw();
    }
    
    void displayScene(final PGraphics3D canvas) {
      canvas.directionalLight(255, 255, 255, 200, 600, 400);
      canvas.directionalLight(255, 255, 255, -200, -600, -400);
      canvas.ambientLight(64, 64, 64);
    
      if (canvas == geombuffer.pg_geom) {
        canvas.background(-1);
        canvas.pgl.clearColor(1, 1, 1, ZFAR);
        canvas.pgl.clear(PGL.COLOR_BUFFER_BIT);
      }
    
      if (shp_scene == null)  shp_scene = makeShape();
      canvas.shape(shp_scene);
    }
    
    PShape makeShape() {
      final PShape scene = createShape(GROUP);
    
      pushStyle();
      colorMode(HSB, 360, 1, 1);
      noStroke();
    
      if (FIXED_SEED)  randomSeed(SEED);
    
      for (int i = 0; i < BOXES; ++i) {
        final float px = random(XMIN, XMAX), py = random(YMIN, YMAX);
        final float sx = random(BOX_DIAM, BOX_DIAM), sy = random(BOX_DIAM, BOX_DIAM);
        final float sz = random(ZMIN, ZMAX);
    
        fill(random(-45, 45), 1, random(.1, 1));
        final PShape shp_box = createShape(BOX, sx, sy, sz);
        shp_box.translate(px, py, sz*.5);
        scene.addChild(shp_box);
      }
    
      for (int i = 0; i < SPHERES; ++i) {
        final float px = random(XMIN, XMAX), py = random(YMIN, YMAX);
        final float pz = random(ZMIN, ZMAX), rr = random(SPH_MIN_D, SPH_MAX_D);
    
        fill(random(205, 245), 1, random(.1, 1));
        final PShape shp_sphere = createShape(PShape.GEOMETRY);
        shp_sphere.scale(rr);
        shp_sphere.translate(px, py, pz);
        scene.addChild(shp_sphere);
    
        if ((i&1) == 0)
          DwMeshUtils.createPolyhedronShape(shp_sphere, cube_facets, 1, 4, false);
        else
          DwMeshUtils.createPolyhedronShape(shp_sphere, cube_smooth, 1, 4, true);
      }
    
      fill(BASE_COL);
      scene.addChild(createShape(RECT, BB_COORD, BB_COORD, BB_DIAM, BB_DIAM));
    
      popStyle();
      return scene;
    }
    
    static final void clearFormatter(final Formatter f) {
      ((StringBuilder) f.out()).setLength(0);
    }
    
    void setTitle() {
      clearFormatter(formatter);
      getSurface().setTitle(formatter.format(TITLE, frameRate).toString());
    }
    
    void printCam() {
      final float[] pos = peasy.getPosition();
      final float[] rot = peasy.getRotations();
      final float[] lat = peasy.getLookAt();
      final double  dis = peasy.getDistance();
    
      clearFormatter(formatter);
    
      println(formatter.
        format(POSITION, pos[0], pos[1], pos[2]).
        format(ROTATION, rot[0], rot[1], rot[2]).
        format(LOOK__AT, lat[0], lat[1], lat[2]).
        format(DISTANCE, dis));
    }
    
  • Randomly selecting blendmode

    To underscore the solution:

    Wrong -- don't use strings:

    var blendModes = ['BLEND', 'ADD'];
    

    Right -- do use the names of built-in constant variables:

    var blendModes = [BLEND, ADD];
    
  • Converting Java code to Python

    I'm back with another question, sorry. I still have a persistent issue with the resizeScreen() function and more particularly with thepg_render and pg_tmp grahics buffers variables.

    When running the .pyde script I get the following error messages:

    GammaCorrection.apply shader | GL_ERROR: invalid operation GammaCorrection.apply | GL_ERROR: invalid operation GammaCorrection.apply | GL_ERROR: invalid framebuffer operation

    This occurs at line 110 (Java script) or 58 (Python version):

    DwFilter.get(context).gamma.apply(pg_render, pg_render)

    Do you know what could be the problem here ?

    Here below, for comparison purposes:

    • a shortened version of the original DoF example sketch in Java (working)
    • the Python transcription of this version (not working)

    Java

    import java.util.Locale;
    import com.jogamp.opengl.GL2;
    import com.thomasdiewald.pixelflow.java.DwPixelFlow;
    import com.thomasdiewald.pixelflow.java.geometry.DwCube;
    import com.thomasdiewald.pixelflow.java.geometry.DwMeshUtils;
    import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DepthOfField;
    import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DwFilter;
    import com.thomasdiewald.pixelflow.java.render.skylight.DwSceneDisplay;
    import com.thomasdiewald.pixelflow.java.render.skylight.DwScreenSpaceGeometryBuffer;
    import com.thomasdiewald.pixelflow.java.utils.DwMagnifier;
    import com.thomasdiewald.pixelflow.java.utils.DwUtils;
    
    import peasy.*;
    import processing.core.PApplet;
    import processing.core.PConstants;
    import processing.core.PShape;
    import processing.opengl.PGL;
    import processing.opengl.PGraphics3D;
    
    
      boolean START_FULLSCREEN = !true;
    
      int viewport_w = 1280;
      int viewport_h = 720;
      int viewport_x = 230;
      int viewport_y = 0;
    
      // camera control
      PeasyCam peasycam;
    
      // library context
      DwPixelFlow context;
    
      PGraphics3D pg_render;
      PGraphics3D pg_dof;
      PGraphics3D pg_tmp;
    
      DepthOfField dof;
      DwScreenSpaceGeometryBuffer geombuffer;
    
      boolean APPLY_DOF = true;
    
    
      public void settings() {
        if(START_FULLSCREEN){
          viewport_w = displayWidth;
          viewport_h = displayHeight;
          viewport_x = 0;
          viewport_y = 0;
          fullScreen(P3D);
        } else {
          size(viewport_w, viewport_h, P3D);
        }
        smooth(0);
      }
    
    
      public void setup() {
    
        // camera
        peasycam = new PeasyCam(this, -4.083,  -6.096,   7.000, 1300);
        peasycam.setRotations(  1.085,  -0.477,   2.910);
    
        // main library context
        context = new DwPixelFlow(this);
        context.print();
        context.printGL();
    
        // callback for scene display (used in GBAA)
        DwSceneDisplay scene_display = new DwSceneDisplay() {  
          @Override
          public void display(PGraphics3D canvas) {
            displayScene(canvas); 
          }
        };
    
        geombuffer = new DwScreenSpaceGeometryBuffer(context, scene_display);
    
        dof = new DepthOfField(context);
    
        frameRate(1000);
      }
    
    
    
      // dynamically resize render-targets
      public boolean resizeScreen(){
    
        boolean[] RESIZED = {false};
    
        pg_render = DwUtils.changeTextureSize(this, pg_render, width, height, 8, RESIZED);
        pg_dof    = DwUtils.changeTextureSize(this, pg_dof   , width, height, 0, RESIZED);
        pg_tmp    = DwUtils.changeTextureSize(this, pg_tmp   , width, height, 0, RESIZED, GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT);
    
    
        peasycam.feed();
        perspective(60 * DEG_TO_RAD, width/(float)height, 2, 6000);
    
        return RESIZED[0];
      }
    
    
    
      public void draw() {
    
        resizeScreen();
    
        displaySceneWrap(pg_render);
    
        DwFilter.get(context).gamma.apply(pg_render, pg_render);
    
        int mult_blur = 30;
        geombuffer.update(pg_render);
    
        DwFilter.get(context).gaussblur.apply(geombuffer.pg_geom, geombuffer.pg_geom, pg_tmp, (int) Math.pow(mult_blur, 0.33f));
    
    ////      dof.param.focus     = map(mouseX, 0, width, 0, 1);
        dof.param.focus_pos = new float[]{0.5f, 0.5f};
        dof.param.focus_pos[0] = map(mouseX+0.5f, 0, width , 0, 1);
        dof.param.focus_pos[1] = map(mouseY+0.5f, 0, height, 1, 0);
        dof.param.mult_blur = mult_blur;
        dof.apply(pg_render, pg_dof, geombuffer);
    
        DwFilter.get(context).copy.apply(pg_dof, pg_render);
    
    
        DwUtils.beginScreen2D(g);
        {
          blendMode(REPLACE);
          clear();
          image(pg_render, 0, 0);    
        }
        DwUtils.endScreen2D(g);
      }
    
    
    
      public void displaySceneWrap(PGraphics3D canvas){
        canvas.beginDraw();
        DwUtils.copyMatrices((PGraphics3D) this.g, canvas);
        // background
        canvas.blendMode(PConstants.BLEND);
        canvas.background(2);
        displayScene(canvas);
        canvas.endDraw();
      }
    
    
    
      // render something
      public void displayScene(PGraphics3D canvas){
        // lights
        canvas.directionalLight(255, 255, 255, 200,600,400);
        canvas.directionalLight(255, 255, 255, -200,-600,-400);
        canvas.ambientLight(64, 64, 64);
    
        if(canvas == geombuffer.pg_geom){
          canvas.background(255, 255);
          canvas.pgl.clearColor(1, 1, 1, 6000);
          canvas.pgl.clear(PGL.COLOR_BUFFER_BIT);
        }
    
    
        sceneShape(canvas);
      }
    
      PShape shp_scene;
    
      public void sceneShape(PGraphics3D canvas){
        if(shp_scene != null){
          canvas.shape(shp_scene);
          return;
        }
    
        shp_scene = createShape(GROUP);
    
        int num_spheres = 50;
        float bb_size = 800;
        float xmin = -bb_size;
        float xmax = +bb_size;
        float ymin = -bb_size;
        float ymax = +bb_size;
        float zmin =  0;
        float zmax = +bb_size;
    
        colorMode(HSB, 360, 1, 1);
    
        DwCube cube_smooth = new DwCube(4);
        DwCube cube_facets = new DwCube(2);
    
        for(int i = 0; i < num_spheres; i++){
          float px = random(xmin, xmax);
          float py = random(ymin, ymax);
          float pz = random(zmin, zmax);
          float rr = random(50) + 50;
          boolean facets = true;//(i%2 == 0);
    
          float off = 20;
          float base = 225;
          float hsb_h = base + random(-off,off);
          float hsb_s = 1;
          float hsb_b = random(0.1f,1.0f);
          int shading = color(hsb_h, hsb_s, hsb_b);
    
          PShape shp_sphere = createShape(PShape.GEOMETRY);
          if(facets){
            DwMeshUtils.createPolyhedronShape(shp_sphere, cube_facets, 1, 4, false);
          } else {
            DwMeshUtils.createPolyhedronShape(shp_sphere, cube_smooth, 1, 4, true);
          }
    
          shp_sphere.setStroke(!true);
          shp_sphere.setStroke(color(0));
          shp_sphere.setStrokeWeight(0.01f / rr);
          shp_sphere.setFill(true);
          shp_sphere.setFill(shading);
          shp_sphere.resetMatrix();
          shp_sphere.scale(rr);
          shp_sphere.translate(px, py, pz);
          shp_scene.addChild(shp_sphere);
        }
    
      }
    

    Python

    add_library('PixelFlow')
    add_library('peasycam')
    from com.jogamp.opengl import GL2
    import java.util.Locale
    
    liste = []
    viewport_w = 1280
    viewport_h = 720
    viewport_x = 0
    viewport_y = 0
    FS = False
    
    def settings():
        global viewport_w, viewport_h
        if FS:
            viewport_w = displayWidth
            viewport_h = displayHeight
            viewport_x = 0
            viewport_y = 0
            fullScreen(P3D)
        else:
            size(viewport_w, viewport_h, P3D)
        smooth(0)
    
    
    def setup():
        global context, scene_display, geombuffer, dof, cam
    
        cam = PeasyCam(this, -4.083,  -6.096,   7.000, 1300)
    
        context = DwPixelFlow(this)
        context.print()
        context.printGL()
    
        scene_display = MySceneDisplay() 
        geombuffer = DwScreenSpaceGeometryBuffer(context, scene_display)
        dof = DepthOfField(context)
    
    
    def resizeScreen():
        global pg_render, pg_dof, pg_tmp
        RESIZED = [False]
        pg_render = DwUtils.changeTextureSize(this, None, width, height, 8, RESIZED)
        pg_dof    = DwUtils.changeTextureSize(this, None, width, height, 0, RESIZED)
        pg_tmp    = DwUtils.changeTextureSize(this, None, width, height, 0, RESIZED, GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT)
    
        cam.feed()
        perspective(60 * DEG_TO_RAD, width/float(height), 2, 6000)
    
        return RESIZED[0]
    
    
    def draw():
        resizeScreen()
    
        displaySceneWrap(pg_render)
    
        DwFilter.get(context).gamma.apply(pg_render, pg_render)
    
        mult_blur = 30
    
        geombuffer.update(pg_render)
    
        DwFilter.get(context).gaussblur.apply(geombuffer.pg_geom, geombuffer.pg_geom, pg_tmp, int(Math.pow(mult_blur, 0.33)))
    
        dof.param.focus_pos = float(0.5, 0.5)
        dof.param.focus_pos[0] = map(mouseX+0.5, 0, width, 0, 1)
        dof.param.focus_pos[1] = map(mouseY+0.5, 0, height, 1, 0)
        dof.param.mult_blur = mult_blur
        dof.apply(pg_render, pg_dof, geombuffer)
    
        DwFilter.get(context).copy.apply(pg_dof, pg_render)
    
        DwUtils.beginScreen2D(g)
        blendMode(REPLACE)
        clear()
        image(pg.render,0,0)
        DwUtils.endScreen2D(g)
    
    
    def displaySceneWrap(canvas):
        canvas.beginDraw()
        DwUtils.copyMatrices(this.g, canvas)
        canvas.blendMode(PConstants.BLEND)
        canvas.background(2)
        displayScene(canvas)
        canvas.endDraw()
    
    def displayScene(canvas):
        canvas.directionalLight(255, 255, 255, 200,600,400)
        canvas.directionalLight(255, 255, 255, -200,-600,-400)
        canvas.ambientLight(64, 64, 64)
    
        if canvas == geombuffer.pg_geom:
            canvas.background(255, 255)
            canvas.pgl.clearColor(1, 1, 1, 6000)
            canvas.pgl.clear(PGL.COLOR_BUFFER_BIT)
    
        sceneShape(canvas)
    
    
    def sceneShape(canvas): 
    
        shp_scene = createShape(GROUP)
    
        if shp_scene != None:
            canvas.shape(shp_scene)
            return   
    
        num_spheres = 50
        bb_size = 800
        xmin = -bb_size
        xmax = +bb_size
        ymin = -bb_size
        ymax = +bb_size
        zmin =  0
        zmax = +bb_size
    
        colorMode(HSB, 360, 1, 1)
    
        cube_smooth = DwCube(4)
        cube_facets = DwCube(2)
    
        for i in range(num_spheres):
            px = random(xmin, xmax)
            py = random(ymin, ymax)
            pz = random(zmin, zmax)
            facets = True
    
            off = 20
            base =225
            hsb_h = base + random(-off, off)
            hsb_s = 1
            hsb_b = random(0.1, 1.0)
            shading = color(hsb_h, hsb_s, hsb_b)
    
        shp_sphere = createShape(PShape.GEOMETRY)
        if facets:
            DwMeshUtils.createPolyhedronShape(shp_sphere, cube_facets, 1, 4, False)
        else:
            DwMeshUtils.createPolyhedronShape(shp_sphere, cube_smooth, 1, 4, True)
    
        shp_sphere.setStroke(False);
        shp_sphere.setStroke(color(0));
        shp_sphere.setStrokeWeight(0.01 / rr);
        shp_sphere.setFill(True);
        shp_sphere.setFill(shading);
        shp_sphere.resetMatrix();
        shp_sphere.scale(rr);
        shp_sphere.translate(px, py, pz);
        shp_scene.addChild(shp_sphere);
    
    
    class MySceneDisplay(DwSceneDisplay): 
        def display(_, canvas): displayScene(canvas)
    
  • Randomly selecting blendmode

    I think your problem is that you're creating Strings rather than using the constants?

    eg. this seems to work - got an error without using constants inside setup()

    var blendModes = [];
    
    function setup() {
      createCanvas(960, 600);
      blendModes = [BLEND, ADD, DARKEST, ADD, DIFFERENCE];
    }
    
  • Randomly selecting blendmode
    int bmode = int(random(14));
    if( bmode == 0 ){
      blendmode(BLEND);
    } else if( bmode == 1 ){
      blendmode(ADD);
    } else ...
    

    It's not pretty, but it'll do it.

    You might luck out... try println(BLEND) (and all the other modes) and see if that is actually a value. Then you could try blendMode(0);, maybe. Maybe.

  • Randomly selecting blendmode

    Is there a way to randomly select blendmode? I tried replacing blendMode(DARKEST) with a variable, but that didn't seem to work. Console log spits out a random blendmode, but when I try to use it it fails.

    var blendModes = ['BLEND', 'ADD', 'DARKEST', 'ADD', 'DIFFERENCE ', 'EXCLUSION', 'MULTIPLY', 'SCREEN', 'REPLACE', 'OVERLAY', 'HARD_LIGHT', 'SOFT_LIGHT', 'DODGE', 'BURN']; //https://p5js.org/reference/#/p5/blendMode

    var randBlendmode = blendModes[Math.floor(Math.random() * blendModes.length)]; console.log(randBlendmode);

    blendMode(randBlendmode);
    

    Test: https://codepen.io/mskogly/pen/ZojbYe?editors=0111 (the blendmode line is commented out)

  • Converting Java code to Python

    I wonder if you 1st was able to transpile back the ".java" sketch as a ".pde" in order to run it under Java Mode? :-?

    • Like removing the statement w/ the package keyword.
    • The public class DepthOfField_Demo extends PApplet { statement & its corresponding closing curly brace.
    • And of course, the whole public static void main(String args[]) { code block. #:-S

    That whole code is æsthetically messy. But here's what I've come w/ as a ".pde" file w/o changing the original ".java" 1 much: :P

    "Depth_of_Field.pde":

    // Depth of Field (DoF) (1.20)
    // Thomas Diewald (diwi) (2017-Oct-07)
    
    // GitHub.com/diwi/PixelFlow/blob/master/examples/Miscellaneous/
    // DepthOfField_Demo/DepthOfField_Demo.java
    
    import static java.util.Locale.ENGLISH;
    
    import com.jogamp.opengl.GL2;
    
    import peasy.PeasyCam;
    
    import com.thomasdiewald.pixelflow.java.DwPixelFlow;
    import com.thomasdiewald.pixelflow.java.geometry.DwCube;
    import com.thomasdiewald.pixelflow.java.geometry.DwMeshUtils;
    import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DepthOfField;
    import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DwFilter;
    import com.thomasdiewald.pixelflow.java.render.skylight.DwSceneDisplay;
    import com.thomasdiewald.pixelflow.java.render.skylight.DwScreenSpaceGeometryBuffer;
    import com.thomasdiewald.pixelflow.java.utils.DwMagnifier;
    import com.thomasdiewald.pixelflow.java.utils.DwUtils;
    
    static final String POSITION = "position: (%7.3f, %7.3f, %7.3f)\n";
    static final String ROTATION = "rotation: (%7.3f, %7.3f, %7.3f)\n";
    static final String LOOK_AT  = "look-at:  (%7.3f, %7.3f, %7.3f)\n";
    static final String DISTANCE = "distance: (%7.3f)\n";
    
    static final String FPS = "   [fps %6.2f]";
    
    boolean start_fullscreen = false;
    
    int viewport_w = 1000;
    int viewport_h = 600;
    int viewport_x = 200;
    int viewport_y = 0;
    
    // camera control
    PeasyCam peasycam;
    
    // library context
    DwPixelFlow context;
    
    PShape shp_scene;
    
    PGraphics3D pg_render;
    PGraphics3D pg_dof;
    PGraphics3D pg_tmp;
    
    DepthOfField dof;
    DwScreenSpaceGeometryBuffer geombuffer;
    
    DwMagnifier magnifier;
    
    boolean apply_dof = true;
    
    void settings() {
      if (!start_fullscreen)  size(viewport_w, viewport_h, P3D);
      else {
        fullScreen(P3D);
        viewport_w = displayWidth;
        viewport_h = displayHeight;
        viewport_x = 0;
        viewport_y = 0;
      }
    
      noSmooth();
    }
    
    void setup() {
      surface.setResizable(true);
      surface.setLocation(viewport_x, viewport_y);
    
      // camera
      peasycam = new PeasyCam(this, -4.083, -6.096, 7.000, 1300);
      peasycam.setRotations(1.085, -0.477, 2.910);
    
      // main library context
      context = new DwPixelFlow(this);
      context.print();
      context.printGL();
    
      // callback for scene display (used in GBAA)
      DwSceneDisplay scene_display = new DwSceneDisplay() {  
        @ Override public void display(PGraphics3D canvas) {
          displayScene(canvas);
        }
      };
    
      geombuffer = new DwScreenSpaceGeometryBuffer(context, scene_display);
    
      dof = new DepthOfField(context);
    
      int mag_h = height/3;
      magnifier = new DwMagnifier(this, 4, 0, height - mag_h, mag_h, mag_h);
    
      frameRate(1000);
    }
    
    void draw() {
      resizeScreen();
      displaySceneWrap(pg_render);
      DwFilter.get(context).gamma.apply(pg_render, pg_render);
    
      int mult_blur = 30;
    
      if (apply_dof) {
        geombuffer.update(pg_render);
    
        DwFilter.get(context).gaussblur.apply(geombuffer.pg_geom, geombuffer.pg_geom, 
          pg_tmp, (int) Math.pow(mult_blur, 0.33));
    
        //      dof.param.focus     = map(mouseX, 0, width, 0, 1);
        dof.param.focus_pos = new float[]{0.5, 0.5};
        dof.param.focus_pos[0] = map(mouseX+0.5, 0, width, 0, 1);
        dof.param.focus_pos[1] = map(mouseY+0.5, 0, height, 1, 0);
        dof.param.mult_blur = mult_blur;
        dof.apply(pg_render, pg_dof, geombuffer);
    
        DwFilter.get(context).copy.apply(pg_dof, pg_render);
      }
    
      magnifier.apply(pg_render, mouseX, mouseY);
      magnifier.displayTool();
    
      DwUtils.beginScreen2D(g);
      //    peasycam.beginHUD();
      {
        blendMode(REPLACE);
        clear();
        image(pg_render, 0, 0);
        //      image(geombuffer.pg_geom, 0, 0);
    
        magnifier.display(g, 0, height-magnifier.h);
    
        blendMode(BLEND);
    
        pushMatrix();
        float cursor_s = 10;
    
        float fpx = dof.param.focus_pos[0] * width;
        float fpy = (1.0 - dof.param.focus_pos[1]) * height;
    
        blendMode(EXCLUSION);
        translate(fpx, fpy);
        strokeWeight(1);
        stroke(255, 200);
        line(-cursor_s, 0, +cursor_s, 0);
        line(0, -cursor_s, 0, +cursor_s);
        blendMode(BLEND);
        popMatrix();
      }
      //    peasycam.endHUD();
      DwUtils.endScreen2D(g);
    
      String txt_fps = String.format(getClass().getName() + FPS, frameRate);
      surface.setTitle(txt_fps);
    }
    
    void keyReleased() {
      if (keyCode == 'C') printCam();
      else if (key == ' ') apply_dof = !apply_dof;
    }
    
    boolean resizeScreen() { // dynamically resize render-targets
      final boolean[] resized = { false };
    
      pg_render = DwUtils.changeTextureSize(this, pg_render, width, height, 8, resized);
      pg_dof    = DwUtils.changeTextureSize(this, pg_dof, width, height, 0, resized);
      pg_tmp    = DwUtils.changeTextureSize(this, pg_tmp, width, height, 0, resized, 
        GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT);
    
      //    geombuffer.resize(width, height)
    
      if (resized[0]) {
        // nothing here
      }
    
      peasycam.feed();
      perspective(60 * DEG_TO_RAD, width/(float)height, 2, 6000);
    
      return resized[0];
    }
    
    void displaySceneWrap(PGraphics3D canvas) {
      canvas.beginDraw();
      DwUtils.copyMatrices((PGraphics3D) this.g, canvas);
    
      canvas.blendMode(PConstants.BLEND);
      canvas.background(2);
      displayScene(canvas);
      canvas.endDraw();
    }
    
    void displayScene(PGraphics3D canvas) {
      canvas.directionalLight(255, 255, 255, 200, 600, 400);
      canvas.directionalLight(255, 255, 255, -200, -600, -400);
      canvas.ambientLight(64, 64, 64);
    
      if (canvas == geombuffer.pg_geom) {
        canvas.background(255, 255);
        canvas.pgl.clearColor(1, 1, 1, 6000);
        canvas.pgl.clear(PGL.COLOR_BUFFER_BIT);
      }
    
      sceneShape(canvas);
    }
    
    void sceneShape(PGraphics3D canvas) {
      if (shp_scene != null) {
        canvas.shape(shp_scene);
        return;
      }
    
      shp_scene = createShape(GROUP);
    
      int num_boxes = 50;
      int num_spheres = 50;
      float bb_size = 800;
      float xmin = -bb_size;
      float xmax = +bb_size;
      float ymin = -bb_size;
      float ymax = +bb_size;
      float zmin =  0;
      float zmax = +bb_size;
    
      colorMode(HSB, 360, 1, 1);
      randomSeed(0);
    
      for (int i = 0; i < num_boxes; i++) {
        float px = random(xmin, xmax);
        float py = random(ymin, ymax);
        float sx = random(200) + 10;
        float sy = random(200) + 10;
        float sz = random(zmin, zmax);
    
        float off = 45;
        float base = 0;
        float hsb_h = base + random(-off, off);
        float hsb_s = 1;
        float hsb_b = random(0.1, 1.0);
        int shading = color(hsb_h, hsb_s, hsb_b);
    
        PShape shp_box = createShape(BOX, sx, sy, sz);
        shp_box.setFill(true);
        shp_box.setStroke(false);
        shp_box.setFill(shading);
        shp_box.translate(px, py, sz*.5);
        shp_scene.addChild(shp_box);
      }
    
      DwCube cube_smooth = new DwCube(4);
      DwCube cube_facets = new DwCube(2);
    
      for (int i = 0; i < num_spheres; i++) {
        float px = random(xmin, xmax);
        float py = random(ymin, ymax);
        float pz = random(zmin, zmax);
        float rr = random(50) + 50;
        boolean facets = true;//(i%2 == 0);
    
        float off = 20;
        float base = 225;
        float hsb_h = base + random(-off, off);
        float hsb_s = 1;
        float hsb_b = random(0.1, 1.0);
        int shading = color(hsb_h, hsb_s, hsb_b);
    
        PShape shp_sphere = createShape(PShape.GEOMETRY);
        if (facets) {
          DwMeshUtils.createPolyhedronShape(shp_sphere, cube_facets, 1, 4, false);
        } else {
          DwMeshUtils.createPolyhedronShape(shp_sphere, cube_smooth, 1, 4, true);
        }
    
        shp_sphere.setStroke(!true);
        shp_sphere.setStroke(color(0));
        shp_sphere.setStrokeWeight(0.01 / rr);
        shp_sphere.setFill(true);
        shp_sphere.setFill(shading);
        shp_sphere.resetMatrix();
        shp_sphere.scale(rr);
        shp_sphere.translate(px, py, pz);
        shp_scene.addChild(shp_sphere);
      }
    
      colorMode(RGB, 255, 255, 255);
    
      PShape shp_rect = createShape(RECT, -1000, -1000, 2000, 2000);
      shp_rect.setStroke(false);
      shp_rect.setFill(true);
      shp_rect.setFill(color(255));
    
      shp_scene.addChild(shp_rect);
    }
    
    PShape createGridXY(int lines, float s) {
      PShape shp_gridxy = createShape();
      shp_gridxy.beginShape(LINES);
      shp_gridxy.stroke(0);
      shp_gridxy.strokeWeight(1);
      float d = lines*s;
    
      for (int i = 0; i <= lines; i++) {
        shp_gridxy.vertex(-d, -i*s, 0); 
        shp_gridxy.vertex(d, -i*s, 0);
        shp_gridxy.vertex(-d, +i*s, 0); 
        shp_gridxy.vertex(d, +i*s, 0);
    
        shp_gridxy.vertex(-i*s, -d, 0); 
        shp_gridxy.vertex(-i*s, d, 0);
        shp_gridxy.vertex(+i*s, -d, 0); 
        shp_gridxy.vertex(+i*s, d, 0);
      }
    
      shp_gridxy.endShape();
      return shp_gridxy;
    }
    
    void printCam() {
      float[] pos = peasycam.getPosition();
      float[] rot = peasycam.getRotations();
      float[] lat = peasycam.getLookAt();
      float   dis = (float) peasycam.getDistance();
    
      System.out.printf(ENGLISH, POSITION, pos[0], pos[1], pos[2]);
      System.out.printf(ENGLISH, ROTATION, rot[0], rot[1], rot[2]);
      System.out.printf(ENGLISH, LOOK_AT, lat[0], lat[1], lat[2]);
      System.out.printf(ENGLISH, DISTANCE, dis);
    }
    
  • Converting Java code to Python

    Thank you for pointing out this omission. Unfortunately, I'm still stuck on line 43:

    for some reason geombuffer.update(pg_render) prevents the sketch from running correctly. I suspect pg_render not to be correctly instantiated...

    add_library('PixelFlow')
    add_library('peasycam')
    from com.jogamp.opengl import GL2
    import java.util.Locale
    
    liste = []
    
    def setup():
        global geombuffer, context, scene_display, dof, magnifier, pg_render, pg_dof, pg_tmp
        size(800, 600, P3D)
        cam = PeasyCam(this, 1000)
        context = DwPixelFlow(this)
        scene_display = MySceneDisplay() 
        geombuffer = DwScreenSpaceGeometryBuffer(context, scene_display)
        dof = DepthOfField(context)
    
        mag_h = int(height/3)
        magnifier = DwMagnifier(this, 4, 0, height - mag_h, mag_h, mag_h)
    
        pg_render = DwUtils.changeTextureSize(this, None, width, height, 8, [False])
        pg_dof    = DwUtils.changeTextureSize(this, None, width, height, 0, [False])
        pg_tmp    = DwUtils.changeTextureSize(this, None, width, height, 0, [False], GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT)
    
        for e in range(100):
            liste.append(PVector(random(width), random(height), random(height)))
    
        cam.feed()
        perspective(60 * DEG_TO_RAD, width/float(height), 2, 6000)
    
        stroke(255)
        strokeWeight(10)
    
    
    def draw():
        background(0)
    
        displaySceneWrap(pg_render)
    
        geombuffer.update(pg_render)
    
    
    def displaySceneWrap(canvas):
        canvas.beginDraw()
        DwUtils.copyMatrices(this.g, canvas)
        canvas.blendMode(PConstants.BLEND)
        canvas.background(2)
        displayScene(canvas)
        canvas.endDraw()
    
    
    def displayScene(canvas):
        canvas.directionalLight(255, 255, 255, 200,600,400)
        canvas.directionalLight(255, 255, 255, -200,-600,-400)
        canvas.ambientLight(64, 64, 64)
    
        if canvas == geombuffer.pg_geom:
            canvas.background(255, 255)
            canvas.pgl.clearColor(1, 1, 1, 6000)
            canvas.pgl.clear(PGL.COLOR_BUFFER_BIT)
    
        sceneShape(canvas)
    
    
    def sceneShape(canvas):
        translate(-width/2, -height/2)
        for e in liste:
            point(e.x, e.y, e.z)
    
    
    class MySceneDisplay(DwSceneDisplay): 
        def display(_, canvas): displayScene(canvas)
    
  • How to compute 3D Delaunay Triangulation ? (with or without library)

    Hi @cansik, thank you for your answer.

    I first though it was because of the missing pushMatrix/popMatrix as well but pushing the transformation matrix doesn't solve the problem.

    When drawing on a canvas:

    • I get 2 pictures at 2 different locations
    • One with the bloom effect (left), the other (right) without it
    • The first one doesn't rotate when moving the camera, the second do
    • The 3D disappears on both pictures (flattened 3D delaunay)

    sketch.pyde

    add_library('peasycam')
    add_library('triangulate')
    add_library('PostFX')
    from java.util import ArrayList
    
    step, threshold = 5, 100
    liste = ArrayList()
    
    def setup():
        global img, triangles, fx, canvas
        size(1800, 1000, P3D)
        smooth(8)
    
        fx = PostFX(this)
        cam = PeasyCam(this, 1600)
        sobel = loadShader('sobelFrag.glsl')
        img = loadImage("test75.jpg")
    
        canvas = createGraphics(width, height, P3D)
    
        pg = createGraphics(img.width, img.height, P2D)
        pg.beginDraw()
        pg.image(img, 0, 0)
        pg.filter(GRAY)
        pg.filter(sobel)
        pg.loadPixels()
        for x in range(0, pg.width, step):
            for y in range(0, pg.height, step):
                i = x + y * pg.width
                col = img.pixels[i]
                b = pg.pixels[i] & 0xFF
                if b > threshold:
                    liste.add(PVector(x, y , brightness(col) * .5))
    
        for e in range(0, pg.width, int(pg.width/20)):
            liste.add(PVector(e, 0, 0))
            liste.add(PVector(e, pg.height, 0))
        for e in range(0, pg.height, int(pg.height/20)):
            liste.add(PVector(0, e, 0))
            liste.add(PVector(pg.width, e, 0))
    
        pg.endDraw()
        triangles = Triangulate.triangulate(liste)
    
    
    def draw():
        background(0)
    
        canvas.pushMatrix()
        canvas.translate(-img.width/2, -img.height/2)
        canvas.beginDraw()
        canvas.beginShape(TRIANGLES)
        canvas.noStroke()
        for t in triangles:
            x = int((t.p1.x + t.p2.x + t.p3.x) / 3)
            y = int((t.p1.y + t.p2.y + t.p3.y) / 3)
            i = x + y * img.width
            col = img.pixels[i]
            canvas.fill(col)
            canvas.vertex(t.p1.x, t.p1.y, t.p1.z)
            canvas.vertex(t.p2.x, t.p2.y, t.p2.z)
            canvas.vertex(t.p3.x, t.p3.y, t.p3.z)
        canvas.endShape() 
        canvas.endDraw()
        canvas.popMatrix()
    
        blendMode(BLEND)
        image(canvas,0,0)
    
        blendMode(SCREEN)
    
        fx.render(canvas).bloom(0.5, 20, 40).compose()
    
  • How to compute 3D Delaunay Triangulation ? (with or without library)

    So, I tried to draw the vertices on a canvas and then applying a bloom effect on this canvas but i still get strange artifacts.

    in setup

    PostFX fx;
    PGraphics canvas;
    
    void setup()
    {
      size(500, 500, P2D);
    
      fx = new PostFX(this);  
      canvas = createGraphics(width, height, P3D);
    }
    

    in draw

    void draw()
    {
      canvas.beginDraw();
      // draw something onto the canvas
      canvas.endDraw();
    
      blendMode(BLEND);
      image(canvas, 0, 0);
    
      // add bloom filter
      blendMode(SCREEN);
      fx.render(canvas)
        .brightPass(0.5)
        .blur(20, 50)
        .compose();
    }
    

    Maybe @cansik have an idea what could possibly be wrong ?

  • Frame Rate keeps getting lower

    Hi

    I working on a code running particles to represent refugee data The code limits the number of particles to keep the frameRate but even after using a steady number of particles, it keeps getting slower with lower frameRate.

    I'm really not sure what I can do to make this run faster / smoother. Why does it keep getting slower?

    Here's the data folder for the Sketch: https://www.dropbox.com/sh/z69phco3tahqklu/AAB8PLMpBQMoFUX5NGSie-5fa?dl=0

    PImage texture;
    PGraphics pg;
    PShape worldMap;
    import java.util.Map;  
    int filterPSystemsNum;
    
    PGraphics sumPG;
    
    // ========== Table Data Stuff 
    
    Table immigrationTable;
    Table conflictTable;
    Table countryLocations;
    
    int k = 0;
    String[] destCountryArray = new String[0];
    String[] sourceCountryArray = new String[0];
    
    String destCountry = "";
    String prevDestCountry = "";
    
    String sourceCountry;
    
    float mapMultiplyX = 4;
    float mapOffsetX = -100;
    float mapMultiplyY = 4;
    float mapOffsetY = 50;
    
    // ========
    
    int amountSum = 1;
    
    String displayType = "Circular";
    
    int maxParticles = 9000;
    
    ParticleSystem ps;
    ParticleSystem ps2;
    
    int n = 0, n2=0;
    int emmitMultiplyer = 1;
    int emmitFreq = 1;
    float particleSpeed = 1;
    
    float locationX = 250;
    float locationY = 450;
    
    int[] sourceX = {10, 40, 200, 400, 700};
    int[] destX = {300, 600, 300, 600, 600};
    int[] amount = {10, 100, 500, 800, 1000};
    int highestAmount;
    
    float radius = 300;
    
    float tempLong;
    float tempLat;
    
    int yearFilterMin = 1996;
    int yearFilterMax = 2016;
    
    
    ParticleSystem[] PSystems;
    
    HashMap<String, Country> countries = new HashMap<String, Country>();
    
    void setup() {
      size(1200, 800, P2D);
      ((PGraphicsOpenGL)g).textureSampling(3);
    
      texture = loadImage("paper_texture.jpg");
      //worldMap = loadShape("worldLow.svg");
    
      //=============== load immigrationTable and create an array of countries
    
    
      immigrationTable = loadTable("asylum_seekers_all.csv", "header");
      countryLocations = loadTable("LatLonCountries2.csv", "header");
      conflictTable = loadTable("ged171.csv", "header");
    
      destCountryArray = (String[]) append(destCountryArray, "Israel");
    
      sumPG = createGraphics(width, height);
    
      pg = createGraphics(width, height);
      pg.beginDraw();
      pg.background(177);
    
      pg.endDraw();
      image(pg, 0, 0);
    
      for (TableRow row : immigrationTable.rows()) {
        if (row.getInt("Year") <= yearFilterMax && row.getInt("Year") >= yearFilterMin) {
    
          String tempCountryHolder = row.getString("Country / territory of asylum/residence");
    
          boolean exists = countryExists(tempCountryHolder);
          if (exists==true) {
    
            continue;
          }
    
          destCountryArray = (String[]) append(destCountryArray, tempCountryHolder);
        }
      }
    
      for (TableRow row : immigrationTable.rows()) {
        if (row.getInt("Year") <= yearFilterMax && row.getInt("Year") >= yearFilterMin) {
    
          String tempCountryHolder = row.getString("Origin");
    
          boolean exists = countryExists(tempCountryHolder);
          if (exists==true) { //println("exists, skipping");
            continue;
          }
          destCountryArray = (String[]) append(destCountryArray, tempCountryHolder);
        }
      }
      destCountryArray = sort(destCountryArray);
    
    
    
      //============================ country hashmaps ======================================
    
      for (int i = 0; i < destCountryArray.length; i++) {
        String name = destCountryArray[i];
    
    
    
    
        for (TableRow row : countryLocations.rows()) {
    
    
          if (name.equals(row.getString("name"))) {
    
            tempLong = row.getFloat("longitude");
            tempLat = row.getFloat("latitude");
          }
        }
    
        countries.put(name, new Country(name, width/2+(tempLong*mapMultiplyX)+mapOffsetX, height/2-(tempLat*mapMultiplyY)+mapOffsetY));
    
      }
    
      for (String key : countries.keySet()) {
        Country c = countries.get(key);
    
      }
    
      //============================ PSystems =============
    
      PSystems = new ParticleSystem[immigrationTable.getRowCount()];
      int j = 0;
    
    highestAmount = 291664;
    
      println(amountSum);
      for (TableRow row : immigrationTable.rows()) {
        if (row.getInt("Year") <= yearFilterMax && row.getInt("Year") >= yearFilterMin) {
          int tempAmount = row.getInt("decisions_recognized");
          String tempDestCountry = row.getString("Country / territory of asylum/residence");
          String tempSourceCountry = row.getString("Origin");
          int tempYear = row.getInt("Year");
    
          float sourceEmmiterX = countries.get(tempSourceCountry).x;
          float sourceEmmiterY = countries.get(tempSourceCountry).y;
          float destEmmiterX = countries.get(tempDestCountry).x;
          float destEmitterY = countries.get(tempDestCountry).y;
    
          PSystems[j] = new ParticleSystem(1, new Vector3D(sourceEmmiterX, sourceEmmiterY, 0), new Vector3D(destEmmiterX, destEmitterY, 0), tempAmount, tempYear);
          println("----");
          filterPSystemsNum++;
    
          println("tempAmount "+tempAmount);
          println("maxParticles "+maxParticles);
          println("amountSum "+amountSum);
          println("tempAmount*maxParticles "+tempAmount*maxParticles);
          println("tempAmount*(maxParticles/amountSum) "+tempAmount*maxParticles/amountSum); 
          //println("PSystems " + i + " is " +PSystems[i]);
          j++;
        }
      }
    
      smooth();
    }
    int currentYear = 2000;
    void draw() {
    
      blendMode(MULTIPLY);
      background(247, 245, 246, 1);
      fill(1, 1, 1, 1);
    
      tint(255, 1);
      image(pg, 0, 0);
    
      for (int i = 0; i<filterPSystemsNum; i++) {
    
        boolean overCountryOrigin = overCountry(int(PSystems[i].origin.x), int(PSystems[i].origin.y), 10);
        boolean overCountryDest = overCountry(int(PSystems[i].dest.x), int(PSystems[i].dest.y), 10);
        boolean isOver = (overCountryOrigin || overCountryDest);
        PSystems[i].run(isOver);
      }
    
    
      //  =======
    
      int allPCount = 0;
      for (int k = 0; k<filterPSystemsNum; k++) {
    
        Vector3D b=new Vector3D(PSystems[k].origin.x, PSystems[k].origin.y+abs(PSystems[k].origin.x-PSystems[k].dest.x)/2, 0);
        Vector3D c=new Vector3D(PSystems[k].dest.x, PSystems[k].dest.y+abs(PSystems[k].origin.x-PSystems[k].dest.x)/2, 0);
    
    
        boolean isTherePLimit = PSystems[k].PLimit != 0;
    
        if (isTherePLimit){
    
        boolean isThisAPlayingFrame = frameCount % int(sqrt(highestAmount/PSystems[k].PLimit)) == 0;
        boolean isThisTheRightYear = PSystems[k].year == currentYear;
        boolean areThereAnyMoreParticles = PSystems[k].PCount<PSystems[k].PLimit;
    
        if (isThisAPlayingFrame && isThisTheRightYear && areThereAnyMoreParticles) {
          for(int s = 0; s<emmitMultiplyer; s++){
          PSystems[k].addParticle();
          PSystems[k].PCount++;
          n++;
          }
        }
      }
        }
    
    
    
      // =========================================================== country labels
    
    
    
    
      for (int i = 0; i<destCountryArray.length; i++) {
        float tempX = countries.get(destCountryArray[i]).x;
        float tempY = countries.get(destCountryArray[i]).y;
        float tempAng = atan((tempY-height/2)/(tempX-width/2));
        float labelMargin;
        translate(tempX, tempY);
        textSize(8);
    
        rotate(tempAng);
        fill(0);
        if (tempX<width/2) {
          textAlign(RIGHT);
          labelMargin = -7;
        } else {
          textAlign(LEFT);
          labelMargin = 7;
        }
    
        if (overCountry(int(tempX), int(tempY), 9)==true) {
          fill(50, 100, 250);
          ellipse(0, 0, 5, 5);
          fill(0, 0, 255);
          text(countries.get(destCountryArray[i]).name, labelMargin, 2);
        } else {
          fill (200);
          fill(30, 100-sq(dist(mouseX, mouseY, tempX, tempY)));
          text(countries.get(destCountryArray[i]).name, labelMargin, 2);
        }
    
        if (countries.get(destCountryArray[i]).name == "Israel") {
    
          textAlign(RIGHT);
          textSize(10);
          fill(255);
          rotate(-tempAng);
          translate(-tempX, -tempY);
          rect(-6, -8, -textWidth("you are here")-7, 14);
    
          fill(200, 40, 40);
          text ("you are here", mouseX, mouseY);
          noFill();
          strokeWeight(0.5);
          stroke(255, 0, 0);
    
          bezier(mouseX, mouseY, (mouseX+tempX)/2+100, mouseY, tempX, (mouseY+tempY)/2, tempX, tempY);
          noStroke();
          translate(tempX, tempY);
          rotate(tempAng);
          ellipse(0, 0, 4, 4);
        }
        rotate(-tempAng);
        translate(-tempX, -tempY);
      }
    
      fill(0);
      text("Frame rate: "
        + int(frameRate), 10, 20);
      text("Each point: " + int(amountSum/maxParticles) +" people", 10, 30);
      text("number of refugees: " + n*int(amountSum/maxParticles), 10, 40);
      text("number of particles is: " +n, 10, 50);
      text("max particles is: " +maxParticles, 10, 60);
      textSize(80);
      blendMode(BLEND);
      fill(128, 130, 131);
      text(round(float(n)*float(amountSum)/float(maxParticles)), 10, 160);
      textSize(20);
      text("RECOGNIZED REFUGEES (" +yearFilterMin+ " - " + yearFilterMax+")", 10, 180);
    
      println("n = "+n);
      println("amountSum = "+amountSum);
      println("maxParticles = "+maxParticles);
    }
    
    
    
    
    // ==============================//  A simple Particle class  // ===============================================//
    
    
    
    
    class Particle {
    
      Vector3D loc;
      Vector3D des;
      Vector3D vel;
      Vector3D acc;
      Vector3D locHome, b, c;
      float relativeSpeed;
    
      float r;
      float timer;
    
      float t=0.0; 
      float a = random(TWO_PI);
      Particle(Vector3D l, Vector3D m, int accum) {
    
        acc = new Vector3D(0, 0, 0); //  new Vector3D(random(-0.1, 0.1), random(-0.02, 0), 0);
        loc = l.copy();
        des = m.copy();
        locHome = l.copy();
    
        float rescale = 0.5;
    
        locHome.x = locHome.x+ cos(a)*random(0, sqrt(accum)*rescale);
        locHome.y = locHome.y+ sin(a)*random(0, sqrt(accum)*rescale);
    
    
        des.x = des.x+ cos(a)*random(0, sqrt(accum)*rescale);
        des.y = des.y+ sin(a)*random(0, sqrt(accum)*rescale);
    
        relativeSpeed = random(0.1, 0.02);
    
    
        r = random(0.9, 3);  // particle radius
        timer = 10000.0;   // particles lifespan
    
    
        b=new Vector3D(l.copy().x, l.copy().y+abs(l.copy().x-m.copy().x)/2, 0);
        c=new Vector3D(m.copy().x, m.copy().y+abs(l.copy().x-m.copy().x)/2, 0);
    
      }
    
      void run(boolean onMouseOverPSystem) {
        update();
        render(onMouseOverPSystem);
      }
    
    
    
      // Method to update location
      void update() {
        if (t>=1)
          return;
    
        loc.x = bezierPoint(locHome.x, b.x, c.x, des.x, t);
        loc.y = bezierPoint(locHome.y, b.y, c.y, des.y, t);
    
        t = lerp(t, 1, particleSpeed*relativeSpeed/2);
    
      }
    
      void render(boolean isSelected) {
        ellipseMode(CENTER);
        noStroke();
        blendMode(BLEND);
    
        if (isSelected == false) {
          fill(128, 129, 129, 150);
        } 
        if (t==lerp(0, 1, particleSpeed*relativeSpeed/2)) {
          pg.beginDraw();
          pg.blendMode(BLEND);
          pg.fill(0, 0, 0);
          pg.noStroke();
          pg.ellipse(loc.x, loc.y, r, r);
          pg.endDraw();
        } else { 
          fill(4*255*t-3*255);
        }
        ellipse(loc.x, loc.y, r, r);
    
      }
    
      // Is the particle still useful?
      boolean dead() {
        if (t==1) {
          pg.beginDraw();
          pg.blendMode(BLEND);
          pg.fill(255, 255, 255, 255);
          pg.noStroke();
          pg.ellipse(loc.x, loc.y, r, r);
          pg.endDraw();
          return true;
        } else {
          return false;
        }
      }
    }
    
    
    // ==============================//  A ParticleSystem  // ===============================================// 
    
    
    // A class to describe a group of Particles
    // An ArrayList is used to manage the list of Particles
    class ParticleSystem {
    
      ArrayList particles;    // An arraylist for all the particles
      Vector3D origin;        // An origin point for where particles are birthed
      Vector3D dest;
      int PLimit;
      int PCount;
      int year;
    
      float ratio = PLimit/highestAmount;
    
      //ParticleSystem( number of particles / frame, source, destination, frequency);
      ParticleSystem(int num, Vector3D v, Vector3D d, int f, int y) {
        particles = new ArrayList();              // Initialize the arraylist
        origin = v.copy();     // Store the origin point
        dest = d.copy();
        year = y;
        PLimit = f;
    
    
        //if (frameCount % (1/f) == 0){
        for (int i = 0; i < num; i++) {
          //  particles.add(new Particle(origin, dest));    // Add "num" amount of particles to the arraylist
        }
        //}
      }
    
      void run(boolean onMouseOverPSystem) {
    
    
        for (int i = particles.size()-1; i >= 0; i--) {
          Particle p = (Particle) particles.get(i);
          p.run(onMouseOverPSystem);
          if (p.dead()) {
            particles.remove(i);
            //PCount--;
            //n--;
          }
    
        }
      }
    
      void addParticle() {
        particles.add(new Particle(origin, dest, PCount));
      }
    
    
    
      // A method to test if the particle system still has particles
      boolean dead() {
        if (particles.isEmpty()) {
          return true;
        } else {
          return false;
        }
      }
    }
    
    //=================================================== Class Country
    
    class Country {
      String name;
      float x, y, lon, lat, migrationIndex, incoming, outgoing;
      // more things here?
    
      Country(String name, float x, float y) {
        this.name = name;
        this.x = x;
        this.y = y;
      }
    }
    
    // ================================================ Simple Vector3D Class
    
    
    public class Vector3D {
    
      public float x;
      public float y;
      public float z;
    
      Vector3D(float x_, float y_, float z_) {
        x = x_; 
        y = y_; 
        z = z_;
      }
    
      Vector3D(float x_, float y_) {
        x = x_; 
        y = y_; 
        z = 0f;
      }
    
      Vector3D() {
        x = 0f; 
        y = 0f; 
        z = 0f;
      }
    
      void setX(float x_) {
        x = x_;
      }
    
      void setY(float y_) {
        y = y_;
      }
    
      void setZ(float z_) {
        z = z_;
      }
    
      void setXY(float x_, float y_) {
        x = x_;
        y = y_;
      }
    
      void setXYZ(float x_, float y_, float z_) {
        x = x_;
        y = y_;
        z = z_;
      }
    
      void setXYZ(Vector3D v) {
        x = v.x;
        y = v.y;
        z = v.z;
      }
    
      public float magnitude() {
        return (float) Math.sqrt(x*x + y*y + z*z);
      }
    
      public Vector3D copy() {
        return new Vector3D(x, y, z);
      }
    
      public Vector3D copy(Vector3D v) {
        return new Vector3D(v.x, v.y, v.z);
      }
    
      public void add(Vector3D v) {
        x += v.x;
        y += v.y;
        z += v.z;
      }
    
      public void sub(Vector3D v) {
        x -= v.x;
        y -= v.y;
        z -= v.z;
      }
    
      public void mult(float n) {
        x *= n;
        y *= n;
        z *= n;
      }
    
      public void div(float n) {
        x /= n;
        y /= n;
        z /= n;
      }
    
      public void normalize() {
        float m = magnitude();
        if (m > 0) {
          div(m);
        }
      }
    
      public void limit(float max) {
        if (magnitude() > max) {
          normalize();
          mult(max);
        }
      }
    
      public float heading2D() {
        float angle = (float) Math.atan2(-y, x);
        return -1*angle;
      }
    
      public Vector3D add(Vector3D v1, Vector3D v2) {
        Vector3D v = new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
        return v;
      }
    
      public Vector3D sub(Vector3D v1, Vector3D v2) {
        Vector3D v = new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
        return v;
      }
    
      public Vector3D div(Vector3D v1, float n) {
        Vector3D v = new Vector3D(v1.x/n, v1.y/n, v1.z/n);
        return v;
      }
    
      public Vector3D mult(Vector3D v1, float n) {
        Vector3D v = new Vector3D(v1.x*n, v1.y*n, v1.z*n);
        return v;
      }
    
      public float distance (Vector3D v1, Vector3D v2) {
        float dx = v1.x - v2.x;
        float dy = v1.y - v2.y;
        float dz = v1.z - v2.z;
        return (float) Math.sqrt(dx*dx + dy*dy + dz*dz);
      }
    }
    
    boolean countryExists(String tempCountryHolder) {
    
      for (int i = 0; i < destCountryArray.length; i++) {
    
        if (tempCountryHolder.equals(destCountryArray[i]) == true) {
    
          return true; // it exists
        } //if
      } //for
      return false ; // not found
    }//func
    
    
    //============================================= onMouseOver Bolean Class
    
    
    boolean overParticle(int x, int y, int diameter) {
      float disX = x - mouseX;
      float disY = y - mouseY;
      if (sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
        return true;
      } else {
        return false;
      }
    }
    
    boolean overCountry(int x, int y, int diameter) {
      float disX = x - mouseX;
      float disY = y - mouseY;
      if (sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
        return true;
      } else {
        return false;
      }
    }
    
  • Code coloring for Processing in LaTeX listings package

    This is something I had up on this forum since last summer, but it was in a question thread so I thought I should share this here in the proper category as well.

    Current version: v1.2

    This LaTeX listings template will color your Processing code as you see them in the Processing editor. You can just post your code like you normally would using the listings package, and you will automatically get your code in the proper colors. Except one minor inconvenience, that I will explain here.

    For a function name that is the same as an already defined keyword (Such as "boolean" and "boolean()"), you have to use [escapechar = "char"] and \color{"color"}{"text"} to color them properly. Example:

    \begin{lstlisting}[escapechar = ?]
    boolean;
    ?\color{function}{boolean}?(1);
    \end{lstlisting}
    

    Copy and paste the below template if you want to use it. Alternatively, you can copy only the necessary parts. If in that case, note that \usepackage{listings} and \usepackage{color} is a must for this to work.

    Also note, I have licensed this work with CreativeCommons license CC-BY-SA, so please remember to give some credit to me ;)

    If you find any typos or any other errors, please tell me and I'll try to fix them as much as possible.

    Download version:
    http://www.mediafire.com/file/cw861uy156xftkv/article_listing_Processing_v1.2.tex
    GitHub Gist:
    https://gist.github.com/ebigunso/af355220e932f72d03289c576622aa29

    Full template below:

    \documentclass{article}
    
    \usepackage{graphicx}
    \usepackage{url}
    \usepackage{verbatim}
    \usepackage{listings}
    \usepackage{color}
    
    % Processing language definition template for LaTeX listings package v1.2
    %
    % Credits to ebigunso for creating this LaTeX listings language definition template for Processing
    % This template is licensed with CreativeCommons license CC-BY-SA 4.0
    % license info:
    % https://creativecommons.org/licenses/by-sa/4.0/legalcode
    
    %Define Colors
    \definecolor{black}{RGB}{0,0,0}
    \definecolor{gray}{RGB}{102,102,102}        %#666666
    \definecolor{function}{RGB}{0,102,153}      %#006699 lightblue
    \definecolor{lightgreen}{RGB}{102,153,0}    %#669900
    \definecolor{bluegreen}{RGB}{51,153,126}    %#33997e
    \definecolor{magenta}{RGB}{217,74,122}  %#d94a7a
    \definecolor{orange}{RGB}{226,102,26}       %#e2661a
    \definecolor{purple}{RGB}{125,71,147}       %#7d4793
    \definecolor{green}{RGB}{113,138,98}        %#718a62
    
    \lstdefinelanguage{Processing}{
      %keyword1&2&6
      morekeywords = [3]{abstract, break, class, continue, default, enum, extends, false, final, finally, implements, import, instanceof, interface, native, new, null, package, private, protected, public, static, strictfp, throws, transient, true, void, volatile, length, assert, case, return, super, this, throw},
      %keyword3
      morekeywords = [4]{catch, do, for, if, else, switch, synchronized, while, try},
      %keyword4
      morekeywords = [5]{width, height, pixelHight, displayHeight, displayWidth, focused, frameCount, frameRate, key, keyCode, keyPressed, mouseButton, mousePressed, mouseX, mouseY, pixels, pixelWidth, pmouseX, pmouseY},
      %keyword5
      morekeywords = [6]{Array, ArrayList, Boolean, Byte, BufferedReader, Character, Class, Double, Float, Integer, HashMap, PrintWriter, String, StringBuffer, StringBuilder, Thread, boolean, byte, char, color, double, float, int, long, short, FloatDict, FloatList, IntDict, IntList, JSONArray, JSONObject, PFont, PGraphics, PImage, PShader, PShape, PVector, StringDict, StringList, Table, TableRow, XML},
      %literal2
      morekeywords = [7]{ADD, ALIGN_CENTER, ALIGN_LEFT, ALIGN_RIGHT, ALPHA, ALPHA_MASK, ALT, AMBIENT, ARC, ARROW, ARGB, BACKSPACE, BASELINE, BEVEL, BLEND, BLUE_MASK, BLUR, BOTTOM, BOX, BURN, CENTER, CHATTER, CHORD, CLAMP, CLICK, CLOSE, CMYK, CODED, COMPLAINT, COMPOSITE, COMPONENT, CONCAVE_POLYGON, CONTROL, CONVEX_POLYGON, CORNER, CORNERS, CROSS, CUSTOM, DARKEST, DEGREES, DEG_TO_RAD, DELETE, DIAMETER, DIFFERENCE, DIFFUSE, DILATE, DIRECTIONAL, DISABLE_ACCURATE_2D, DISABLE_DEPTH_MASK, DISABLE_DEPTH_SORT, DISABLE_DEPTH_TEST, DISABLE_NATIVE_FONTS, DISABLE_OPENGL_ERRORS, DISABLE_PURE_STROKE, DISABLE_TEXTURE_MIPMAPS, DISABLE_TRANSFORM_CACHE, DISABLE_STROKE_PERSPECTIVE, DISABLED, DODGE, DOWN, DRAG, DXF, ELLIPSE, ENABLE_ACCURATE_2D, ENABLE_DEPTH_MASK, ENABLE_DEPTH_SORT, ENABLE_DEPTH_TEST, ENABLE_NATIVE_FONTS, ENABLE_OPENGL_ERRORS, ENABLE_PURE_STROKE, ENABLE_TEXTURE_MIPMAPS, ENABLE_TRANSFORM_CACHE, ENABLE_STROKE_PERSPECTIVE, ENTER, EPSILON, ERODE, ESC, EXCLUSION, EXIT, FX2D, GIF, GRAY, GREEN_MASK, GROUP, HALF, HALF_PI, HAND, HARD_LIGHT, HINT_COUNT, HSB, IMAGE, INVERT, JAVA2D, JPEG, LEFT, LIGHTEST, LINE, LINES, LINUX, MACOSX, MAX_FLOAT, MAX_INT, MIN_FOAT, MIN_INT, MITER, MODEL, MOVE, MULTIPLY, NORMAL, NORMALIZED, NO_DEPTH_TEST, NTSC, ONE, OPAQUE, OPEN, ORTHOGRAPHIC, OVERLAY, PAL, PDF, P2D, P3D, PERSPECTIVE, PI, PIE, PIXEL_CENTER, POINT, POINTS, POSTERIZE, PRESS, PROBLEM, PROJECT, QUAD, QUAD_STRIP, QUADS, QUARTER_PI, RAD_TO_DEG, RADIUS, RADIANS, RECT, RED_MASK, RELEASE, REPEAT, REPLACE, RETURN, RGB, RIGHT, ROUND, SCREEN, SECAM, SHAPE, SHIFT, SPAN, SPECULAR, SPHERE, SOFT_LIGHT, SQUARE, SUBTRACT, SVG, SVIDEO, TAB, TARGA, TAU, TEXT, TFF, THIRD_PI, THRESHOLD, TIFF, TOP, TRIANGLE, TRIANGLE_FAN, TRIANGLES, TRIANGLE_STRIP, TUNER, TWO, TWO_PI, UP, WAIT, WHITESPACE},
      %function1
      morekeywords = [8]{start, stop, breakShape, createPath, str, loadMatrix, parseBoolean, parseByte, parseChar, parseFloat, parseInt, saveFile, savePath, sketchFile, sketchPath, abs, acos, alpha, ambient, ambientLight, append, applyMatrix, arc, arrayCopy, asin, atan, atan2, background, beginCamera, beginContour, beginRaw, beginRecord, beginShape, bezier, bezierDetail, bezierPoint, bezierTangent, bezierVertex, binary, blend, blendColor, blendMode, blue, box, brightness, camera, ceil, clear, clip, color, colorMode, concat, constrain, copy, cos, createFont, createGraphics, createImage, createInput, createOutput, createReader, createShape, createWriter, cursor, curve, curveDetail, curvePoint, curveTangent, curveTightness, curveVertex, day, degrees, delay, directionalLight, displayDensity, dist, ellipse, ellipseMode, emissive, endCamera, endContour, endRaw, endRecord, endShape, exit, exp, expand, fill, filter, floor, frustum, fullScreen, get, green, hex, hint, hour, hue, image, imageMode, join, launch, lerp, lerpColor, lightFalloff, lights, lightSpecular, line, loadBytes, loadFont, loadImage, loadJSONArray, loadJSONObject, loadPixels, loadShader, loadShape, loadStrings, loadTable, loadXML, log, loop, mag, map, match, matchAll, max, millis, min, minute, modelX, modelY, modelZ, month, nf, nfc, nfp, nfs, noClip, noCursor, noFill, noise, noiseDetail, noiseSeed, noLights, noLoop, norm, normal, noSmooth, noStroke, noTint, ortho, parseJSONArray, parseJSONObject, parseXML, perspective, list, pixelDnsity, point, pointLight, popMatrix, popStyle, pow, print, printArray, printCamera, println, printMatrix, printProjection, pushMatrix, pushStyle, quad, quadraticVertex, radians, random, randomGaussian, randomSeed, rect, rectMode, red, redraw, requestImage, resetMatrix, resetShader, reverse, rotate, rotateX, rotateY, rotateZ, round, saturation, save, saveBytes, saveFrame, saveJSONArray, saveJSONObject, saveStream, saveStrings, saveTable, saveXML, scale, screenX, screenY, screenZ, second, selectFolder, selectInput, selectOutput, set, shader, shape, shapeMode, shearX, shearY, shininess, shorten, sin, size, smooth, sort, specular, sphere, sphereDetail, splice, split, splitTokens, spotLight, sq, sqrt, stroke, strokeCap, strokeJoin, strokeWeight, subset, tan, text, textAlign, textAscent, textDescent, textFont, textLeading, textMode, textSize, texture, textureMode, textureWrap, textWidth, thread, tint, translate, triangle, trim, unbinary, unhex, updatePixels, vertex, year},
      %function2
      morekeywords = [9]{cache, readLine, close, flush, print, println, charAt, equals, indexOf, substring, toLowerCase, toUpperCase, getDouble, getLong, getColumnTitles, getColumnTypes, getColumnType, setDouble, setLong, add, clear, div, get, hasKey, keyArray, keys, mult, remove, set, size, sortKeys, sortKeysReverse, sortValues, sortValuesReverse, sub, valueArray, values, append, array, hasValue, max, min, mult, remove, reverse, shuffle, sort, sortReverse, increment, getBoolean, getFloat, getInt, getIntArray, getJSONArray, getJSONObject, getString, getStringArray, isNull, setBoolean, setFloat, setInt, setJSONArray, setJSONObject, setString, beginDraw, endDraw, blend, copy, filter, loadPixels, mask, resize, save, updatePixels, addChild, beginContour, beginShape, disableStyle, enableStyle, endContour, endShape, getChild, getChildCount, getVertex, getVertexCount, isVisible, resetMatrix, rotate, rotateX, rotateY, rotateZ, scae, setFill, setStroke, setVertex, setVisible, translate, angleBetween, cross, dist, dot, fromAngle, heading, lerp, limit, mag, magSq, normalize, randm2D, random3D, setMag, lower, upper, addColumn, addRow, clearRows, findRow, findRows, getColumnCount, getRow, getRowcount, getStringColumn, matchRow, matchRows, removeColumn, removeRow, removeTokens, rows, trim, getColumnTitle, format, getAttributeCount, getChildren, getContent, getNam, getParent, hasAttribute, hasChildren, listAttributes, listChildren, removeChild, setContent, setName, toString},
      %function4
      morekeywords = [10]{draw, keyReleased, keyTyped, mouseClicked, mouseDragged, mouseMoved, mouseReleased, mouseWheel, settings, setup},
      keywordstyle = [3]\color{bluegreen},
      keywordstyle = [4]\color{lightgreen},
      keywordstyle = [5]\color{magenta},
      keywordstyle = [6]\color{orange},
      keywordstyle = [7]\color{green},
      keywordstyle = [8]\color{function},
      keywordstyle = [9]\color{function},
      keywordstyle = [10]\color{function},
      sensitive = true,
      morecomment = [l][\color{gray}]{//},
      morecomment = [s][\color{gray}]{/*}{*/},
      morecomment = [s][\color{gray}]{/**}{*/},
      morestring = [b][\color{purple}]",
      morestring = [b][\color{purple}]'
    }
    \renewcommand{\ttdefault}{pcr}
    \lstset{
      language={Processing},
      basicstyle={\small\ttfamily},
      identifierstyle={\small},
      commentstyle={\small\itshape},
      keywordstyle={\small},
      ndkeywordstyle={\small},
      stringstyle={\small\ttfamily},
      frame={tb},
      breaklines=true,
      columns=[l]{fullflexible},
      numbers=left,
      xrightmargin=0em,
      xleftmargin=3em,
      numberstyle={\scriptsize},
      stepnumber=1,
      numbersep=1em,
      lineskip=-0.5ex,
    }
    
    % Use escapechar and \color{<color>}{<text>} to color function names properly, that is already defined as a different color keyword.
    %
    % \begin{lstlisting}[escapechar = ?]
    % boolean;
    % ?\color{function}{boolean}?(1);
    % \end{lstlisting}
    
    \title{}
    \author{}
    \date{}
    
    \begin{document}
    \maketitle
    \section{}
    
    \begin{thebibliography}{9}
    \end{thebibliography}
    \end{document}
    
  • losing transparency when loading png file from jar into PImage

    I'm guessing it's an efficiency thing. If there's no alpha then you don't need to worry about the current value of the screen pixel you're just about to overwrite, you can just copy the new value over it. If there is alpha involved then you have to blend the two.

  • Countdown Class library for Java, JS & Python

    p5.js JS Version:

    http://Bl.ocks.org/GoSubRoutine/1a0d21828319cf18fecf44101764bd60

    "index.html":

    <script async src=http://CDN.JSDelivr.net/npm/p5></script>
    <script defer src=countdown.js></script>
    <script defer src=sketch.js></script>
    

    "sketch.js":

    /**
     * Countdown Class (v1.2.5)
     * GoToLoop (2017/Aug/29)
     *
     * Forum.Processing.org/two/discussion/27733/
     * countdown-class-library-for-java-js-python#Item_1
     *
     * Forum.Processing.org/two/discussion/23846/
     * time-delay-in-python-mode#Item_16
     *
     * Bl.ocks.org/GoSubRoutine/1a0d21828319cf18fecf44101764bd60
     */
    
    "use strict";
    
    const SECS = 7.5, WAIT_TIME = SECS * 1000 | 0,
          AWAIT = SECS, END = 'Finished', LF = '\n',
          countdown = new Countdown(WAIT_TIME);
    
    let waitingBG, doneBG;
    
    function setup() {
      createCanvas(300, 180);
      frameRate(60);
    
      colorMode(RGB).blendMode(BLEND);
      fill('yellow').stroke(0).strokeWeight(1.5);
      textSize(0o100).textAlign(CENTER, CENTER);
    
      waitingBG = color('blue');
      doneBG = color('red');
    
      const m = ~~millis(), t = m + WAIT_TIME;
      countdown.start();
      console.log(m, t, t - m, countdown.toString());
      status = m + ', ' + t + ', ' + (t - m);
    }
    
    function draw() {
      top.document.title = countdown.done && END || AWAIT;
      background(countdown.done && doneBG || waitingBG);
    
      const txt = ~~millis() + LF + frameCount;
      text(txt, width>>1, height>>1);
    }
    

    "countdown.js":

    /**
     * Countdown Class (v1.2.5)
     * GoToLoop (2017/Aug/29)
     *
     * https://Forum.Processing.org/two/discussion/27733/
     * countdown-class-library-for-java-js-python#Item_1
     *
     * https://Forum.Processing.org/two/discussion/23846/
     * time-delay-in-python-mode#Item_16
     *
     * http://Bl.ocks.org/GoSubRoutine/1a0d21828319cf18fecf44101764bd60
     */
    
    "use strict";
    
    class Countdown {
      get delay() {
        return this._delay;
      }
    
      set delay(waitTime) {
        this._delay = ~~Math.abs(waitTime);
      }
    
      constructor(waitTime=0) { // milliseconds
        this.delay = waitTime;
        this.done = true;
        this._timeout = () => this.done = true;
        this.task = 0;
      }
    
      toString() {
        return 'Delay: ' + this.delay + '  -  Done: ' + this.done;
      }
    
      start() {
        clearTimeout(this.task);
        this.done = false;
        this.task = setTimeout(this._timeout, this.delay);
        return this;
      }
    }
    
  • Get RadialGradientPaint to work in processing 3

    I found this code on github that works fine on processing 2, but doens't on processing 3. It is supossed to draw radial gradients influenced by the mouse position using a java library. But in processing 3 it just shows a grey screen. I tried altering some things and a lot of google searches but I can't find the cause.

    I had to add this line for it to find PGraphicsJava2D too:

    import processing.awt.PGraphicsJava2D;
    import java.awt.Graphics2D;
    import java.awt.RadialGradientPaint;
    import java.awt.Color;
    import java.awt.geom.*;
    
    Graphics2D g2;
    Rectangle2D.Double rectangle;
    
    Point2D center;
    Point2D focus;
    float radius;
    float[] dist = { 0.0f, 0.4f, 1.0f };
    
    Color[] gradColors = new Color[dist.length];
    
    Color[] endColors = {
        new Color(254, 189, 75), // yellow
        new Color(255, 98, 43), // red
        new Color(87, 25, 198) // violet
    };
    
    Color[] startColors = {
        new Color(232, 185, 71),
        new Color(180, 98, 56),
        new Color(87, 36, 68)
    };
    
    void setup() {
      size(300, 600); // make sure NOT to use P2D
      g2 = ((PGraphicsJava2D)g).g2;
    
      rectangle = new Rectangle2D.Double(0, 0, width, height);
      radius = height;
      center = new Point2D.Float(width/2.0f, height);
      focus = new Point2D.Float(width/2.0f, height);
      updateColors(0);
    }
    
    void draw() {
      RadialGradientPaint gradient =
             new RadialGradientPaint(center,
                                     radius, 
                                     focus,
                                     dist, 
                                     gradColors,
                                     RadialGradientPaint.CycleMethod.NO_CYCLE);
      g2.setPaint(gradient);
      g2.fill(rectangle);
    }
    
    void mouseMoved() {
      updateColors((float) mouseY / height);
    }
    
    void updateColors(double blend) {
      for(int i = 0; i < gradColors.length; i++) {
        gradColors[i] = lerpColor(startColors[i], endColors[i], blend);
      }
    }
    
    Color lerpColor(Color color1, Color color2, double blend) {
      double inverseBlend = 1.0 - blend;
      int redPart = (int) (color1.getRed() * blend + color2.getRed() * inverseBlend);
      int greenPart = (int) (color1.getGreen() * blend + color2.getGreen() * inverseBlend);
      int bluePart = (int) (color1.getBlue() * blend + color2.getBlue() * inverseBlend);
      return new Color(redPart, greenPart, bluePart);
    }
    
  • Arrays. Getting separate arrays of bubbles to emit at x,y coordinates of array of moving objects.

    I decided to come up with my own solution, maybe it can help you out. Keep in mind I just started java/processing last week. My big problem is figuring out how to do things efficiently. There are a many things that could be improved here. Because I just reset the location back to the origin as soon as it leaves the screen eventually patterns will emerge. You can also make it a looping array instead of just running through a large array of particle objects. Also the speed of emission, movement, collisions etc. could be added. But I hope it just serves as one simple example for how arrays and loops work.

    View the result: https://gfycat.com/BigheartedMeaslyBeaver

    int index;
    int max;
    
    Effects blend;
    classyEmitters[] classy = new classyEmitters[2];
    Bubblies[] nenoo = new Bubblies[1000];
    
    void setup() {
      size(600, 600);
      blend = new Effects();
      classy[0] = new classyEmitters();
      classy[1] = new classyEmitters();
      for (int i = 0; i < nenoo.length; i++) {
        nenoo[i] = new Bubblies();
      }
    
      index = 0;
      max = 0;
    }
    
    void draw () {
      background(0);
      textSize(24);
      textAlign(CENTER, CENTER);
      fill(255);
      text(frameRate, width/2, height/2);
      if (index > 100 & index < nenoo.length) {
        max++;
      }
    
      classy[0].getSchwifty(width/2, height/2, 5, 10, 200);
      classy[1].getSchwifty(width/2, height/2, -5, 20, 100);
      for (int i = max; i< index; i++) {
        nenoo[i].moveBubblies();
        nenoo[i].showBubblies();
      }
      if (index < nenoo.length) {
        index++;
      }
    }
    
    class classyEmitters {
    
      int xprev;
      int yprev;
      int xcur;
      int ycur;
      int rotation;
    
      classyEmitters() {
    
        xprev=0;
        yprev=0;
        xcur=0;
        ycur=0;
        rotation=0;
      }
    
    
      void getSchwifty(int x, int y, int zoomZoom, float soBig, float soFar) {
    
        xcur= int(cos(radians(rotation))*soFar) + x;
        ycur = int(sin(radians(rotation))*soFar) + y;
        rotation = rotation + zoomZoom;
    
        drawEllipse(xcur, ycur, soBig);
        xprev = xcur;
        yprev = ycur;
      }
    
      void drawEllipse(float x, float y, float size) {
    
        blend.blender(3, xprev, x, yprev, y, size, 255, 255, 255, 5);
    
        fill(255);
    
        ellipse(xcur, ycur, size, size);
      }
    }
    
    class Effects {
    
      Effects() {
      }
    
      void blender(int a, float b, float c, float d, float e, float f, float g, float h, float ii, float j) {
        int Count = a + 1;
        float x1 = b;
        float x2 = c;
        float y1 = d;
        float y2 = e;
        float size = f;
        float R = g;
        float G = h;
        float B = ii;
        float Alpha = j;
        noStroke();
        for (int i = 1; i < Count; i++) {
          fill(R, G, B, i*Alpha);
          ellipse(x1+ (x2 - x1) * i/Count, y1 + (y2 - y1) * i/Count, size, size);
        }
      }
    }
    
    class Bubblies {
      boolean spawned = false;
      float x;
      float y;
      int which;
      Bubblies() {
        float x = 0;
        float y = 0;
        which = int(random(0, 2));
      }
    
      void moveBubblies() {
    
        if (!spawned || y < -5) {
          x = classy[which].xcur;
          y = classy[which].ycur;
          spawned = true;
        } else { 
          y -= 1;
          x += random(-2, 2);
        }
      }
    
      void showBubblies() {
    
        if (which == 0) {
          fill(40, 74, 20);
        } else {
          fill(50, 20, 60);
        }
        if (y > -5) {
          ellipse(x, y, 10, 10);
        }
      }
    }
    
  • Help needed with P3D on Android

    I'm not familiar with Processing Android development, but could an equivalent to needing a depth hint have something to do with it? Something like z-fighting, and using hint(DISABLE_DEPTH_TEST)...?

    Ah, I just read @codeanticode's response on the issue thread:

    As it turns out, the problem was caused by the getStyle/style() calls when pausing/resuming the sketch, as they were interfering with the blend modes in the UI. Saving/restoring the sketch style is not needed, the value of the style variables in PApplet is not lost when pausing the sketch (although saving the contents of the surface view is needed). Commit 62bfa77 fixes the issue.

  • How to create a blend between two different 3D objects

    Very true, Jeremy! I posted about this in c4dcafe as well, and user Rectro came up with a solution for c4d that is very much in line with your idea. https://www.c4dcafe.com/ipb/forums/topic/101520-blend-two-different-objects/?tab=comments#comment-668812