www.jpct.net

jPCT-AE - a 3d engine for Android => Support => Topic started by: Nodin on June 11, 2010, 05:10:05 am

Title: How to do 2D click to 3D object picking?
Post by: Nodin on June 11, 2010, 05:10:05 am
How can I take a touch event on the display and project it into world coordinates and pick a world object?

Previously using jPCT I had success using the object ids with something like;

SimpleVector position=new SimpleVector(Interact2D.reproject2D3D(camera, buffer, x, y));
int[] res=Interact2D.pickPolygon(theWorld.getVisibilityList(), position);

..but that's not supported in jPCT-AE?

Thanks!
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on June 11, 2010, 07:45:53 am
These methods in Interact2D work in camera space, i.e. on the visiblity list. For compiled objects, that visibility list actually doesn't exist (in fact it does, but it's content has changed), which is why you can't use these methods on compiled objects. In AE, all objects are being rendered as compiled object, which is why the method is gone. You have to use something like calcMinDistance() instead. This thread has some information about it:http://www.jpct.net/forum2/index.php/topic,1468.0.html (http://www.jpct.net/forum2/index.php/topic,1468.0.html).
Title: Re: How to do 2D click to 3D object picking?
Post by: Nodin on June 11, 2010, 07:52:44 pm
Thanks, I did finally get a touch point to project a ray into the world, but I can't pick an object.

Using calcMinDistanceAndObject3D always returns empty, even when I can see my ray hitting an object.

Object[] result = getWorld().calcMinDistanceAndObject3D(camera.getPosition(), ray, 10000F);

result[0] always has a float
result[1] is always null

Any ideas?
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on June 11, 2010, 09:53:25 pm
ray has to be transformed in world space before (not visible in your code snippet if you actually do this or not) and the objects you want to pick have to be colliders, i.e. Object3D.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS); has to be set.
Title: Re: How to do 2D click to 3D object picking?
Post by: Nodin on June 12, 2010, 05:08:04 pm
Thanks, it was the collision check setting!

Cloned objects don't have the setting of the original.
Title: Re: How to do 2D click to 3D object picking?
Post by: pritom057 on July 04, 2010, 04:26:50 pm

still it does not work perfectly

I did this
Code: [Select]

//SimpleVector position = new SimpleVector(Interact2D.reproject2D3DWS(world.getCamera(), fb, (int) x,(int) y));
SimpleVector position = new SimpleVector(Interact2D.reproject2D3D(world.getCamera(), fb, (int)x,(int)y, 10.f));
   
   position.matMul(world.getCamera().getBack().invert3x3());
   position.add(world.getCamera().getPosition());
   
   Object[] result = world.calcMinDistanceAndObject3D(world.getCamera().getPosition(), position, .01F);

but the problem is it always returns the object which is neat from camera

I have also used reproject2D3DWS(..) to same thing happened
any idea how can we do this??
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on July 04, 2010, 09:41:32 pm
It's an engine's bug...and it's in desktop jPCT too. Strange that nobody (including myself) ever noticed it. I've uploaded a version of AE that should fix it here: http://www.jpct.net/jpct-ae/download/alpha/jpct_ae.jar (http://www.jpct.net/jpct-ae/download/alpha/jpct_ae.jar) as well as a fixed jar for desktop jPCT here: http://www.jpct.net/download/beta/jpct.jar (http://www.jpct.net/download/beta/jpct.jar).

Please note that in your example, the upper bars obviously count for the touch events, i.e. if you touch at the beginning of the actual gl canvas, the y coordinate isn't 0 but something like 50. You have to take this into account when giving the y-coordinate to Interact2D. In your example, i have to touch 50 pixels above the trees to hit them.
Title: Re: How to do 2D click to 3D object picking?
Post by: Ilse on July 18, 2010, 09:03:28 am
Hi,

I want to do the same like you, but I can get it working.

I use the demo and set the "plane" -> plane.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);

then (with the x and y from the touch event ) I do the same like you:

SimpleVector position = new SimpleVector(Interact2D.reproject2D3D(world.getCamera(), fb, (int)x,(int)y, 10.f));         
position.matMul(world.getCamera().getBack().invert3x3());
position.add(world.getCamera().getPosition());         
Object[] result = world.calcMinDistanceAndObject3D(world.getCamera().getPosition(), position, .01F);

but the resulting float is always -> 1.0E12 == Object3D.RAY_MISSES_BOX

can you give mw a hint or a working example

Thanks
Ilse

P.S. I am using the last version from the main page (http://www.jpct.net/jpct-ae/download/alpha/jpct_ae.jar)
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on July 18, 2010, 10:25:57 am
.01F as the last parameter of calcMinDistance of much too low. Anything farer away than this value is will be excluded from the calculation. Try something like 100, 1000 or 10000 (depending on your scene).
Title: Re: How to do 2D click to 3D object picking?
Post by: smither on August 31, 2010, 07:11:03 pm
I have the same problem that Ilse had, i always get 1.0E12 no matter what value i use for the last parameter.

Any idea?
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on August 31, 2010, 08:14:03 pm
If you are sure that the collision set properly and that the last parameter is fine too, try to adjust Config.collideOffset to a higher value and see if that helps.
Title: Re: How to do 2D click to 3D object picking?
Post by: smither on September 01, 2010, 08:55:35 pm
What's more expensive in terms of performance? Call to calcMinDistanceAndObject3D or just check a collision between the position the user click on the screen?

Because if i can have a confirmation from the listener I won't have to figure out how to fix the issue unless the difference between these 2 approaches is too much.
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on September 01, 2010, 11:09:18 pm
That depends on the type of collision detection you are using!?
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on September 01, 2010, 11:28:54 pm
Also make sure that the direction vector given to calcMinDistanceAndObject3D is a unit vector...
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on September 06, 2010, 09:57:42 pm
Because this is a common topic and the forum contains some wrong code for picking, i decided to add a page to the wiki: http://www.jpct.net/wiki/index.php/Picking (http://www.jpct.net/wiki/index.php/Picking)
Title: Re: How to do 2D click to 3D object picking?
Post by: Ulrick on November 16, 2010, 11:01:01 am
Hi Egon,

just to be sure I'm doing it right, in JPCT-AE, if I use the following:

Object3D picked=world.getObject(result[1]);

I get always a null pointer.

while if I use the following:

 Object3D picked=(Object3D)result[1];

I get it right.

Is it correct?

Thanks,

Ulrick
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on November 16, 2010, 12:03:54 pm
result is the return value of which method here?
Title: Re: How to do 2D click to 3D object picking?
Post by: Ulrick on November 16, 2010, 03:54:11 pm
I got your sample code from the Wiki (http://www.jpct.net/wiki/index.php/Picking):

-- EXTRACT --
SimpleVector dir=Interact2D.reproject2D3D(camera, frameBuffer, x, y);
int[] res=Interact2D.pickPolygon(world.getVisibilityList(), dir);

In res, you'll find the polygon- and the object number (in that order), if the picking actually picked something. If not, res is null. Your picked Object3D is now

(*) Object3D picked=world.getObject(res[1]);
-- EXTRACT --

But that works probably for the Desktop version of JPCT (I didn't tested it).

In JPCT-AE, doing the same, will just give a null pointer executing the marked (*) line of code

While casting to Object3D return the right value:

 Object3D picked=(Object3D)result[1];

I was writing just to be sure it was the correct way in JPCT-AE.

Thanks,

Ulrick
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on November 16, 2010, 08:33:32 pm
What really confuses me, is that there is no pickPolygon(...)-method in AE...so i don't get how you can compare the output of those two methods if one doesn't exist ??? That said, the way that uses the cast is the correct one for AE and so it's written in the wiki:
Quote
It's the only one that is available in jPCT-AE
.
Title: Re: How to do 2D click to 3D object picking?
Post by: jmachete on December 20, 2010, 03:15:09 pm
I guys,

I'm following the wiki but I still haven't make this work yet. I'm doing this inside the method "onDrawFrame", so I'm a bit confusing in terms of how I can get the picked object in the end.

When I reproject what is going to be my X and Y, the position of my camera?

SimpleVector dir=Interact2D.reproject2D3DWS(cam, fb, (int)cam.getXAxis().x, (int)cam.getXAxis().y);

and who I pickup the object?

Object3D picked=res[1] ????

this is the code I'm using:

Code: [Select]
public void onDrawFrame(GL10 gl) {

try {
if (!stop) {
Camera cam = world.getCamera();

SimpleVector dir=Interact2D.reproject2D3DWS(cam, fb, (int)cam.getXAxis().x, (int)cam.getXAxis().y);
dir.matMul(world.getCamera().getBack().invert3x3());
dir.add(world.getCamera().getPosition());  

if (turn != 0) {
world.getCamera().rotateY(-turn);
}

if (touchTurn != 0) {
world.getCamera().rotateY(touchTurn);
touchTurn = 0;
}

if (touchTurnUp != 0) {
world.getCamera().rotateX(touchTurnUp);
touchTurnUp = 0;
}

if (move != 0) {
world.getCamera().moveCamera(cam.getDirection(), move);
}

Object[] res=world.calcMinDistanceAndObject3D(cam.getPosition(), dir, 10000 /*or whatever*/);
if(res[1]!=null)
Object3D picked=res[1]; //??????????????? I'm confuse

fb.clear(back);
world.renderScene(fb);
world.draw(fb);
blitNumber(lfps, 5, 5);

fb.display();

if (box != null) {
box.rotateX(0.01f);
}

if (sun != null) {
sun.rotate(sunRot, plane.getTransformedCenter());
}

if (System.currentTimeMillis() - time >= 1000) {
lfps = fps;
fps = 0;
time = System.currentTimeMillis();
}
fps++;
} else {
if (fb != null) {
fb.dispose();
fb = null;
}
}
} catch (Exception e) {
e.printStackTrace();
Logger.log("Drawing thread terminated!", Logger.MESSAGE);
}

Hope anyone can give me some light.

Cheers
Joao
Title: Re: How to do 2D click to 3D object picking?
Post by: raft on December 21, 2010, 02:25:38 pm
you need to cast the result to Object3D.

Code: [Select]
if(res[1]!=null)
   Object3D picked=(Object3D) res[1];
Title: Re: How to do 2D click to 3D object picking?
Post by: jmachete on December 21, 2010, 02:58:26 pm
But from where I can get the X and Y values from:

SimpleVector dir=Interact2D.reproject2D3DWS(cam, fb, x, y);


??

Title: Re: How to do 2D click to 3D object picking?
Post by: raft on December 21, 2010, 03:13:24 pm
x, y are the screen coordinates that you want to pick the Object3D behind. it depends on your application but typically the coordinates user touched at screen. something like this:

override onTouchEvent in your activity
Code: [Select]
int screenX = -1, screenY = -1;

@Override
public boolean onTouchEvent(MotionEvent event) {
   switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
            screenX = (int) event.getX();
            screenY = (int) event.getY();
            break;
        }
case MotionEvent.ACTION_UP: {
            screenX = -1;
            break;
        }
}

then in your onDrawFrame method:
Code: [Select]
if (screenX != -1) {
   SimpleVector dir=Interact2D.reproject2D3DWS(cam, fb, screenX, screenY);
   //...
}
Title: Re: How to do 2D click to 3D object picking?
Post by: PaldxD on February 22, 2011, 02:04:06 pm
Why this never work?
i set all collisions right, and res[1] is null ever
:(

Code: [Select]
{
if (xpos != -1) {
SimpleVector dir = Interact2D.reproject2D3DWS(cam,
fb, (int) xpos, (int) ypos);
dir.matMul(world.getCamera().getBack().invert3x3());
dir.add(world.getCamera().getPosition());
Object[] res = world.calcMinDistanceAndObject3D(
cam.getPosition(), dir, 10000);
if (res[1] != null)
player_Corpo.setAdditionalColor(RGBColor.WHITE);
else
player_Corpo.setAdditionalColor(RGBColor.BLUE);
}
}
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on February 22, 2011, 02:10:41 pm
Because you are mixing things there. You are doing a kind of multiple world space transformation, which makes no sense. Have a look at this thread: http://www.jpct.net/forum2/index.php/topic,1932.0.html (http://www.jpct.net/forum2/index.php/topic,1932.0.html)
Title: Re: How to do 2D click to 3D object picking?
Post by: PaldxD on February 22, 2011, 02:30:18 pm
tried that too.
i wanna make a mp3 player with jpct-ae, and i need check if the click has in player or in pauser for example.

Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on February 22, 2011, 02:39:16 pm
Well, "tried that too" is a bit vague. The method definitely works fine. If it doesn't work for you, you did something wrong...but that's impossible to tell given the information you provided. Do you have a simple test case of something?
Title: Re: How to do 2D click to 3D object picking?
Post by: PaldxD on February 22, 2011, 03:12:25 pm
 i'm really dumb, works fine thx.
Title: Re: How to do 2D click to 3D object picking?
Post by: SpiRaiL on April 13, 2011, 11:45:29 pm
ok, so i followed the whole thread and have it working as expected.

Now i want to do things with the object that i picked, but i have many objects.

I have a class "box" and i extend the object3D class.

and then i pick one. But i want to be able to drag that specific box around the screen.
If i to getID on a box it has the id = 0;

but when i cast the result for the picker, and do getID it has the id 1.
Should that make sense?

Really, i want to "pick" my box class, not the object in the super class (im not a Java expert, so maybe i dont know what im talking about).
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on April 14, 2011, 12:04:50 am
That's most likely because your extended class uses another instance of Object3D in the constructor to create the box. So this first instance gets 0 and yours gets 1, as it's the next Object3D being created. What's the actual problem with this behaviour?
Title: Re: How to do 2D click to 3D object picking?
Post by: androidman on May 13, 2011, 06:04:02 am
Hi EgonOlsen,

Based on http://www.jpct.net/wiki/index.php/Picking, it didn't work when i touch on object but if i touch on another area that is beside object --> it work.

Code: [Select]
SimpleVector p = Interact2D.reproject2D3D(camera, frameBuffer, (int)touchPos.x,(int)touchPos.y).normalize();
  Object[] objs= world.calcMinDistanceAndObject3D(camera.getPosition(), p, 1000);

how can i fix it?

i am using  the jpct-ae version that was posted at http://www.jpct.net/forum2/index.php/topic,1561.225.html.



Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on May 13, 2011, 09:37:59 am
You are not working in world space but in camera space. Please look at that wiki page again and use the ....WS-method that it mentions. Also make sure that your touch coordinates match your frame buffer coordinates. Sometimes a status bar or similar shifts the whole thing by a few pixels.
Title: Re: How to do 2D click to 3D object picking?
Post by: androidman on May 16, 2011, 09:21:59 am
Thank you very much, EgonOlsen.

You are right. it worked. :D
Title: Re: How to do 2D click to 3D object picking?
Post by: ginopeloso on November 05, 2014, 05:57:50 pm
What if I don't want the first object in the direction of my click but the one behind it?
In my model I have some objects which are transparent (like glasses); if the user clicks these ones I have to ignore them and try to pick another object behind the clicked one in the same direction of the click (if this one is transparent again the one behind, until I pick a non-transparent object or nothing)

I tried with the following code but did not succeed; the app continues to pick always the same object:
Code: [Select]
SimpleVector dir = Interact2D.reproject2D3D(camera, frameBuffer, screenX, screenY);
Object[] res = world.calcMinDistanceAndObject3D(camera.getPosition(), dir, 10000);
Object3D clickedObject = (Object3D)res[1];
while (clickedObject != null && clickedObject.getName().startsWith("transparent")) {
dir.z = clickedObject.getTransformedCenter().z;
res = world.calcMinDistanceAndObject3D(camera.getPosition(), dir, 10000);
clickedObject = (Object3D)res[1];
}

Is there a way for doing it?
Title: Re: How to do 2D click to 3D object picking?
Post by: EgonOlsen on November 05, 2014, 10:19:24 pm
Just make all transparent objects invisible before doing the picking (and reset them afterwards).