Quantcast
Channel: Library Questions - Processing 2.x and 3.x Forum
Viewing all articles
Browse latest Browse all 2896

Concurrent Modification Exception trying to add objects on OSC event

$
0
0

I'm designing this generative visuals system that uses OSC data from a musician to produce these kind of abstract "asteroids" in real time. I'm running into this Concurrent Modification Exception which I'm assuming has to do with the fact that the OSC Event is another thread (or something? happening alongside my draw loop) and so maybe when iterating through my asteroid objects an asteroid is added, causing an error. I thought the synchronize trick would work, no such luck. Any help is appreciated!

Note: Just tried it with also protecting/removing the .remove() portion of the code, same error (although perhaps less frequent?)

// OSC STUFF
volatile boolean isBusy = false;

/* incoming osc message are forwarded to the oscEvent method. */
void oscEvent(OscMessage theOscMessage) {
    if (theOscMessage.addrPattern().equals("/peter/rhythm")) {
        if (!isBusy)
        asteroids.add(new Asteroid(0));
    }
}


// DRAW STUFF
void wormhole() {
    pg.background(bgColor, bgTrans);

    // there are stars from last scene, animate those suckers
    for (Star s : stars) {
        s.display();
    }

    isBusy = true;
    // update, display asteroids
    synchronized (asteroids) {
        for (Asteroid a : asteroids) {
            a.update();
            a.display();
        }
    }
    isBusy = false;
}


// DELETING ASTEROIDS STUFF FROM DRAW() maybe this needs synch too?
  // destroy anything that is offscreen
  for (int i = asteroids.size() - 1; i >= 0; i--) {
    Asteroid a = asteroids.get(i);
    if (a.dead()) {
      asteroids.remove(i);
    }
  }


// ASTEROID class
float asteroidTrans = 120;  // global transparency modifier for asteroids

class Asteroid {
  PVector pos;
  color cFill, cStroke;

  float r;  // rotation
  float rotateSpeed = .005;

  float sw = 2; //strokeWeight

  float ld = 5; // line distance

  float p;  // phase
  float pRate = .3;  // phase rate
  float pAdjust;  // use this number to add to s [or any other value)

  float speed = 1;
  float s = 1;  // starting size
  float growthRate = .05; // growth per frame

  int type = 0; // type of asteroid

  // properties
  // phase pulsates size of asteroid
  // corona gives it a circular outline
  // death color makes it change space bg color on impact w screen

  // behaviors
  boolean ROTATE, PHASE;
  // shape types
  boolean BOX, SPHERE, LINES, CORONA, TRI;
  // on death/ birth
  boolean DEATH_COLOR;
  // extras

  Asteroid(int type) {
    this.type = type;

    pos = new PVector(random(width), random(height), far);

    // randomize its initial rotation
    r = random(TWO_PI);

    switch (type) {
    case 0: // black cube
      cFill = color(0);
      cStroke = color(255);
      ROTATE = true;
      BOX = true;
      break;
    case 1: // colorful, pulsating circles, on death make bg that color
      sw = 0;

      // random colors
      cFill = color(random(255), random(255), random(255), random(20, 255));
      cStroke = cFill;

      ROTATE = true;
      PHASE = true;
      SPHERE = true;
      CORONA = true;
      DEATH_COLOR = true;
      break;
    case 2: // line creature..?
      LINES = true;
      PHASE = true;
      //CORONA = true;
      //pRate = .001;
      ld = 20;
      sw = 1;
      cStroke = color(255);
      break;
    case 3: // triangles
      TRI = true;
      ROTATE = true;
      PHASE = true;
      cFill = color(255);
      rotateSpeed = .01;
      break;

    }

  }

  void update() {
    // all asteroid types move towards you (and grow)
    pos.z += speed * hyperspaceModifier;
    s += growthRate * hyperspaceModifier;

    // rotating asteroids
    if (ROTATE) {
      r += rotateSpeed * hyperspaceModifier;
    }

    if (PHASE) {
      p += pRate; // inc phase
      pAdjust += sin(p) * .5;
    }
  }

  void display() {

    // TRIANGLE
    if (TRI) {
      pg.pushMatrix();
      pg.translate(pos.x, pos.y, pos.z);
      if (ROTATE) {
        pg.rotateZ(r);
      }
      pg.rotateX(3 * PI / 2);
      pg.stroke(255);
      if (PHASE) {
        float r = map(sin(p), -1, 1, 0, 255);
        float g = map(cos(p), -1, 1, 0, 255);
        float b = map(tan(p), -1, 1, 0, 255);
        cFill = color(r, g, b);
      }
      pg.fill(cFill);

      pg.beginShape(TRIANGLES);
      pg.vertex(-12, -12, -12);
      pg.vertex( 12, -12, -12);
      pg.vertex(   0,    0,  12);

      pg.vertex( 12, -12, -12);
      pg.vertex( 12,  12, -12);
      pg.vertex(   0,    0,  12);

      pg.vertex( 12, 12, -12);
      pg.vertex(-12, 12, -12);
      pg.vertex(   0,   0,  12);

      pg.vertex(-12,  12, -12);
      pg.vertex(-12, -12, -12);
      pg.vertex(   0,    0,  12);
      pg.endShape();

      //pg.triangle(0, -10, 8, 10, -8, 10);
      pg.popMatrix();
    }

    // LINE
    if (LINES) {
      pg.pushMatrix();
      pg.translate(pos.x, pos.y, pos.z);
      pg.stroke(cStroke);
      pg.strokeWeight(sw);

      int segments = 8;

      PVector[] linePV = new PVector[segments];
      linePV[0] = new PVector(0, 0, 0);
      for (int i = 1; i < segments; i++) {
        float x = cos( p + (segments / TWO_PI * i)) * ld * (i * .1);
        float y = sin( p + (segments / TWO_PI * i)) * ld * (i * .1);
        float z = linePV[i - 1].z - ld;

        linePV[i] = new PVector(x, y, z);

        pg.line(linePV[i - 1].x, linePV[i - 1].y, linePV[i - 1].z, x, y, z);
      }

      pg.popMatrix();
    }

    // CORONA
    if (CORONA) {
      pg.pushMatrix();
      pg.translate(pos.x, pos.y, pos.z);
      pg.stroke(cStroke, asteroidTrans);
      pg.noFill();
      pg.strokeWeight(sw + 4 + pAdjust);
      pg.ellipse(0, 0, (s + pAdjust) * 1.3, (s + pAdjust) * 1.3);
      pg.popMatrix();
    }

    // BOX
    if (BOX) {
      pg.pushMatrix();
      pg.translate(pos.x, pos.y, pos.z);
      if (ROTATE) rotate();
      pg.fill(cFill, asteroidTrans);
      pg.strokeWeight(sw);
      pg.stroke(cStroke);
      pg.box(s + pAdjust);
      pg.popMatrix();
    }

    // SPHERE
    if (SPHERE) {
      pg.pushMatrix();
      pg.translate(pos.x, pos.y, pos.z);
      pg.strokeWeight(sw);
      pg.stroke(cStroke);
      pg.fill(cFill, asteroidTrans);
      //pg.sphereDetail(7);
      //if (ROTATE) rotate();
      //pg.sphere(s + pAdjust);
      pg.ellipse(0, 0, s + pAdjust, s + pAdjust);
      pg.popMatrix();
    }
  }

  boolean dead() {
    // if object gets totally offscreen...
    if (pos.z > 1000) {
      // DEATH COLOR asteroids change bg color on impact
      if (DEATH_COLOR) {
        bgColor = cFill;
      }
      return true;  // destroy object
    } else {
      return false;
    }
  }

  // if this asteroid is a rotater
  void rotate() {
    pg.rotateY(r);
    pg.rotateZ(r * 2);
    pg.rotateX(r * 3);
  }
}

Viewing all articles
Browse latest Browse all 2896

Trending Articles