我正在努力修改来自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");
}
}
答案 0 :(得分:0)
tl; dr:当您从另一个线程迭代数据结构时,不应该使用一个线程修改数据结构。
draw()
函数在一个线程上发生,它正在访问和修改物理库中的数据结构。
oscEvent()
函数正在另一个线程上发生,它还访问和修改那些相同的数据结构。这就是造成你的错误的原因。请注意,将其包裹在try
块中不修复任何内容。当错误发生时,它只是打印出更多信息。
要真正解决问题,您需要了解线程之间的同步数据访问。例如,您可以使用synchronized块来防止不同的线程访问相同的数据结构。如果你发现你的错误,你会发现大量的结果。