处理草图

时间:2017-06-05 15:09:01

标签: java processing concurrentmodification

我正在努力修改来自Toxiclibs library的Attraction2D示例,以便通过Leap Motion传感器的手势进行控制,而不是示例中的鼠标。

我在Open Frameworks应用程序中进行所有手势识别,然后通过OSC发送。

发生Gesture 0事件时,我调用以下方法从gestureAttractor对象中删除physics

void resetAttraction() {
  if (gestureAttractor != null){
      physics.removeBehavior(gestureAttractor);
      println("ATTRACTOR NULL");
     } else {
        println("not null");
     }
}

如果发生Gesture 1事件,我会调用此方法创建新的gestureAttractor,然后将其添加回physics对象:

void addAttraction(){ 
   if (gestureAttractor == null) { 
       println("ATTRACTOR NULL"); 
       position1.set(340, 191); 
       gestureAttractor = new AttractionBehavior2D(position1, 250, 0.9f); 
       physics.addBehavior(gestureAttractor); 
   } else { 
       println("not null"); 
   } 
}

似乎一直发生的事情是,只要手势状态发生变化,ConcurrentModificationException方法physics.update();就会draw崩溃。

我确定它与处理这些对象的生命周期的方式有关,但我还没有确定任何东西 - 任何人都有任何想法?

以下是整个草图:

import toxi.geom.*;
import toxi.physics2d.*;
import toxi.physics2d.behaviors.*;

import oscP5.*;
import netP5.*;

OscP5 oscP5;

int NUM_PARTICLES = 750;

VerletPhysics2D physics;
//AttractionBehavior2D mouseAttractor;
AttractionBehavior2D gestureAttractor;


//Vec2D mousePos;
Vec2D position1;


boolean isGestureAttractorAdded;

void setup() {
  size(680, 382,P3D);
  // setup physics with 10% drag
  physics = new VerletPhysics2D();
  physics.setDrag(0.05f);
  physics.setWorldBounds(new Rect(0, 0, width, height));
  // the NEW way to add gravity to the simulation, using behaviors
  physics.addBehavior(new GravityBehavior2D(new Vec2D(0, 0.15f)));

  // start oscP5, listening for incoming messages at port 12000 
  oscP5 = new OscP5(this, 6000);

  position1 = new Vec2D(340, 191);

  addAttraction();

  //gestureAttractor = new AttractionBehavior2D(position1, 250, 0.9f);
  //physics.addBehavior(gestureAttractor);
}

void addParticle() {
  VerletParticle2D p = new VerletParticle2D(Vec2D.randomVector().scale(5).addSelf(width / 2, 0));
  physics.addParticle(p);
  // add a negative attraction force field around the new particle
  physics.addBehavior(new AttractionBehavior2D(p, 20, -1.2f, 0.01f));
}

void draw() {
  background(255,0,0);
  noStroke();
  fill(255);
  if (physics.particles.size() < NUM_PARTICLES) {
    addParticle();
  }
  physics.update();
  for (VerletParticle2D p : physics.particles) {
    ellipse(p.x, p.y, 5, 5);
  }
}

void mousePressed() {
  //position1 = new Vec2D(mouseX, mouseY);
   //create a new positive attraction force field around the mouse position (radius=250px)
  //gestureAttractor = new AttractionBehavior2D(position1, 250, 0.9f);
  //physics.addBehavior(gestureAttractor);

  //println(physics.behaviors);
}

void mouseDragged() {
  // update mouse attraction focal point
  //position1.set(mouseX, mouseY);
}

void mouseReleased() {
  // remove the mouse attraction when button has been released
  //physics.removeBehavior(gestureAttractor);
}


///// OSC RECEIVING

void oscEvent(OscMessage theOscMessage) {
  /* check if theOscMessage has the address pattern we are looking for. */

  if (theOscMessage.checkAddrPattern("/gesture_classification") == true)  {
    /* check if the typetag is the right one. */
    if(theOscMessage.checkTypetag("i")) {
      /* parse theOscMessage and extract the values from the osc message arguments. */
      int gestureClassLabel = theOscMessage.get(0).intValue();  
      println(" Gesture is: ", gestureClassLabel);

      if (gestureClassLabel == 0){   
        resetAttraction();
      } else if (gestureClassLabel == 1) {       
        addAttraction();
      } else if (gestureClassLabel == 2) {
          //physics.removeBehavior(gestureAttractor);
      } 
    }  
  } 

}

//////METHODS FOR SETTING POSITION / REMOVAL OF ATTRACTORS...

void resetAttraction() {
  if (gestureAttractor != null){
      physics.removeBehavior(gestureAttractor);
      println("ATTRACTOR NULL");
     } else {
        println("not null");
     }
 }

void addAttraction(){
     if (gestureAttractor == null) {
         println("ATTRACTOR NULL");
         position1.set(340, 191);
         gestureAttractor = new AttractionBehavior2D(position1, 250, 0.9f);
         physics.addBehavior(gestureAttractor);
     } else {
       println("not null");
     }
}

1 个答案:

答案 0 :(得分:0)

tl; dr:当您从另一个线程迭代数据结构时,不应该使用一个线程修改数据结构。

draw()函数在一个线程上发生,它正在访问和修改物理库中的数据结构。

oscEvent()函数正在另一个线程上发生,它还访问和修改那些相同的数据结构。这就是造成你的错误的原因。请注意,将其包裹在try块中修复任何内容。当错误发生时,它只是打印出更多信息。

要真正解决问题,您需要了解线程之间的同步数据访问。例如,您可以使用synchronized块来防止不同的线程访问相同的数据结构。如果你发现你的错误,你会发现大量的结果。