Loading...
Logo
Processing Forum
So, for a project I'm working on, the Picking library seems absolutely perfect. However, it appears that in the current version of Processing, there have been some changes to the renderer that cause this library not to work. When I import the library, using the Add Library tool, and then call   picker = new Picker(this);, I get a NoClassDefFoundError, on PGraphics3D. To the best of my understanding, PGrapics3D is no longer used, as everything has been switched to OpenGL. Is that correct?

Has anyone found a workaround for this, or better yet, an actual correction? I'd love to be able to use this library. Here is the link to the source code for it.
http://code.google.com/p/processing-picking-library/source/browse/#svn/trunk/Picking/src/picking?state=closed
Thanks!

Replies(13)

Hi Cullam,
I have the same issue, and a strong intrest in getting it resolved, too (like quite a few others, I beleive).
I have no solution, can only share my thoughts of non-specialist:
 
1-  First I tried  to figure if it is a fundamental issue (meaning that we should start looking for an alternative to Picking) , or "just" a configuration issue. I agree with your diagnostic, but a forum comment  (about another issue) stated "  PGraphics3D no longer exists in the processing.core package in Processing 2.0, but now it is in processing.opengl "
 
So, it makes me think that PGraphics3D is still usable, and therefore Picking  might work if properly configurated.
 
2- A direction I tried, was to make sure that my  openGL library was the correct one (not  the old 1.5). Processing official doc states that In Processing 2.0, a new version of the OpenGL library replaces the one found in 1.x releases ... it is now part of the core (no need to use Import Library → OpenGL)
I tried to locate this new OpenGL library in my 2.0 config, but I can't - and since apparently it can't be downloaded separately, I assume that indeed it is imbedded in 2.0, and thereforefool-proof.
 
 
... And that's it ! I am stuck !
Anyone ?       
 
 
I did some looking into re-implementing picking, But I didn't have enough base knowledge to go at it effectively, and couldn't really afford the time into learning enough about it. I've rolled back to Processing 1.5.1, where everything works fine. If the possibility to use picking, or a similar functioning library, comes up in 2.0, I'll re-upgrade.
Hello

I've modified the library picking (Nicolas Clavaud) to work with processing version 2.0.b7.

You can define class  Buffer and  Picker, directly on your processing editor, or netbeans, or eclipse

Buffer Class


Copy code
Copy code
  1. public class Buffer extends PGraphics3D
  2. {
  3.   protected int current_color = 0;
  4.     
  5.   public Buffer(PApplet parent)
  6.   {
  7.     setParent(parent);
  8.     setSize(parent.width, parent.height);    
  9.   }

  10.   @Override
  11.   public boolean displayable() { return true; }
  12.   
  13.   public void callCheckSettings() { super.checkSettings(); }
  14.   
  15.   @Override
  16.   public void lights() {}
  17.   
  18.   @Override
  19.   public void smooth() {}
  20.   
  21.   @Override
  22.   public void fill(int arg) {}
  23.   
  24.   @Override
  25.   public void fill(float arg) {}
  26.   
  27.   @Override
  28.   public void fill(float arg, float arg_1) {}
  29.   
  30.   @Override
  31.   public void fill(int arg, float arg_1) {}
  32.   
  33.   @Override
  34.   public void fill(float arg, float arg_1, float arg_2) {}
  35.   
  36.   @Override
  37.   public void fill(float arg, float arg_1, float arg_2, float arg_3) {}
  38.   
  39.   @Override
  40.   public void stroke(int arg) {}
  41.   
  42.   @Override
  43.   public void stroke(float arg) {}
  44.   
  45.   @Override
  46.   public void stroke(float arg, float arg_1) {}
  47.   
  48.   @Override
  49.   public void stroke(int arg, float arg_1) {}
  50.   
  51.   @Override
  52.   public void stroke(float arg, float arg_1, float arg_2) {}
  53.   
  54.   @Override
  55.   public void stroke(float arg, float arg_1, float arg_2, float arg_3) {}
  56.   
  57.   @Override
  58.   public void textureMode(int arg) {}
  59.   
  60.   @Override
  61.   public void texture(PImage arg) {}
  62.   
  63.   @Override
  64.   public void vertex(float x, float y, float z, float u, float v) { super.vertex(x, y, z); }
  65.   
  66.   @Override
  67.   public void image(PImage arg, float arg_1, float arg_2) {}
  68.   
  69.   @Override
  70.   public void image(PImage arg, float arg_1, float arg_2, float arg_3, float arg_4) {}
  71.   
  72.   @Override
  73.   public void image(PImage arg, float arg_1, float arg_2, float arg_3, float arg_4, int arg_5, int arg_6, int arg_7, int arg_8) {}
  74.   
  75.   @Override
  76.   protected void imageImpl(PImage image, float x1, float y1, float x2, float y2, int u1, int v1, int u2, int v2) {}
  77.   
  78.   public void setCurrentId(int i) 
  79.   {
  80.       // ID 0 to 16777214  => COLOR -16777215 to -1 (white)
  81.       // -16777216 is black
  82.       current_color = i - 16777215;
  83.       super.fill(current_color);      
  84.   }
  85.   
  86.   public int getId(int x, int y)
  87.   {
  88.       super.loadPixels();
  89.       // COLOR -16777216 (black) to -1 => ID -1 (no object) to 16777214 
  90.       int id = pixels[y*width+x] + 16777215;
  91.       return id;
  92.   }
  93. }

Picker Class

Copy code
Copy code
  1. public class Picker 
  2. {
  3.   protected PApplet parent;
  4.   public Buffer buffer;
  5.   
  6.   public Picker(PApplet parent) 
  7.   {
  8.     this.parent = parent;
  9.     buffer = new Buffer(parent);     
  10.     //parent.registerMethod("pre",this);
  11.     //parent.registerMethod("draw",this);
  12.   }      
  13.   
  14.   public void begin() 
  15.   {
  16.     if(parent.recorder == null)
  17.     {
  18.       parent.recorder = buffer; 
  19.       buffer.beginDraw();           
  20.     }
  21.   }
  22.   
  23.   public void end() 
  24.   {
  25.     buffer.endDraw();  
  26.     parent.recorder = null;
  27.   }

  28.   public void start(int i)
  29.   {
  30.     if (i < 0 || i > 16777214)
  31.     {
  32.       PApplet.println("[Picking error] start(): ID out of range");
  33.       return;
  34.     }
  35.     buffer.setCurrentId(i);            
  36.   }
  37.   
  38.   public void stop() 
  39.         {
  40.     parent.recorder = null;
  41.   }
  42.   
  43.   public void resume() 
  44.         {
  45.     parent.recorder = buffer;
  46.   }
  47.   
  48.   public int get(int x, int y)
  49.   {
  50.     return buffer.getId(x, y);
  51.   }
  52.   
  53.   public PGraphics getBuffer()
  54.   {
  55.     return buffer;
  56.   }    
  57. }

Example


Copy code
Copy code
  1. Picker picker;
  2. float a = 0.0;

  3. void setup() 
  4. {  
  5.   size(200,200, P3D);  
  6.   picker = new Picker(this);
  7. }

  8. void draw() 
  9. {    
  10.   background(0,128,0);
  11.   a += 0.01;

  12.   picker.begin();
  13.   
  14.   picker.start(0);
  15.   pushMatrix();
  16.   translate(80, 75);
  17.   rotateX(a);
  18.   rotateY(a);
  19.   fill(200,40,60);
  20.   box(50);
  21.   popMatrix();
  22.   
  23.   picker.start(1);
  24.   pushMatrix();
  25.   translate(140, 75);
  26.   rotateX(a);
  27.   rotateY(a);
  28.   fill(60,40,200);
  29.   box(20);
  30.   popMatrix();
  31.   
  32.   picker.end();
  33.   
  34. }

  35. void mousePressed()
  36. {
  37.   println(picker.get(mouseX, mouseY));
  38. }

I hope that helps somewhat
This solution seems working fine! Thank you.

I'll try to include it into my Augmented Reality experiment and I'll let you know what about .obj files and other features I need there 

Thank you again!

Ciao,
Massimo

EDIT: It did not work as expected read forward!
Important Note:

I don't know exactly why, but for some reason background can't be correctly overloaded, so is very important to call picker.begin() after the background() instruction
I checked and we may have an issue:

if the sketch size is bigger than the 200x200 size in your example I experience a small fps slow down. The problem is more evident with bigger size.

Do you have the same issue?

I found the problem is still the loadPixels() function that take too long. I think we have to find a solution based on andres snippet...

Massimo
I modified the Buffer class in order to avoid this frame rate problem:


As you can see from the code above I mainly avoided loadPixels() function in favor of a clipped pixel array area of 1 pixel at mouse position...

Something like this:

Copy code
  1. pgl.readPixels(x, height - y, 1, 1, PGL.RGBA, PGL.UNSIGNED_BYTE, pixelColorBuffer);

What do you think?

Massimo
Hi massimo

You're right.

With my class Buffer we need to load the entire frame in each loop of the rendering function. 
However with your Buffer class we only load one pixel.

Your class besides being faster is more robust.
Thank you very much for your contribution.
I have tested it and works perfectly. 

I have also another problem, perhaps we can solve.
If we render a PShape object, the picking function does not work properly.

I understand that the PShape class needs to be overloaded like the PGraphics3D class with the Buffer object.

greetings
There is a comment inside PGraphics that is pretty interesting:

Copy code
  1. shape.draw(this); // needs to handle recorder too
I'm investigating but for the moment I did find no more clues 
Hi all

I`ve found a important error in my solution.
the background is not managed properly in the recorder object

I'll try to find a solution
Sorry


In terms of the performance issue, I was able to get the picker to run much faster (and grab the entire frame) by using GLGraphics (in 1.51) and the GLTexture class.  While still slow, the .getTexture() and .updateTexture() commands didn't bog down my sketch nearly as much.  Do you think it would be possible to get this same performance out of Processing 2.0? 

I wonder if you could just create an offscreen buffer and get the performance boost by running it on your GPU rather than using a PImage?

EDIT:  Well, I implemented my Picker code in 2.0 and it's a bit slower without the GLGraphics GLTexture().  I also tested the readPixels() command and it basically freezes if you want the whole buffer (which I do). I don't know how I would parse a larger grab this way (or whether it would be faster).

To make my picker work I use the following basic idea:

Create a PShape that is my mesh colored the appropriate "picker colors", 

When I want to pick it, I draw it noSmooth() on an offscreen buffer called pickerB (just a regular PGraphics3D object). Then execute the following before I start grabbing pixels:

Copy code
  1.  PImage tex = (PImage) pickerB;
Then I use the following to grab the pixels (it's much slower if I use get() or PImage, so this PImage is just a throwaway... ) Strangely this doesn't work with pickerB.loadPixels().

Copy code
  1.   int id = ((PImage)pickerB).pixels[pixelNumber] + 16777215; // 16777215

I can explain the other parts if you like. No classes.
Hey guys,

Sorry, didn't have time lately to upgrade the lib for Processing 2.0.

I have finally managed to find some time to make adjustements, so the library now compiles for Processing 2.0 and I could run the examples, though there is this background issue you have noticed. Also, there may be this performance problem you're talking about.

FIY, the project is now hosted on GitHub, so you can fork and request changes.


Background-related issue is fixed, and Picking library is back in Processing's Library Manager.