[ resolved ] picking of Object3D

Started by cefengxu, December 02, 2015, 10:36:00 AM

Previous topic - Next topic

cefengxu

Hi master :

i want to know the model do some reply when i touch it on the screen, so i use the Picking of jpct-ae  to realized it.
example
i add a cube with six diff. faces  and add setCollisionMode respectively :

     // Front
        front = new Object3D(2); 
        front.addTriangle(upperLeftFront,0,0, lowerLeftFront,0,1, upperRightFront,1,0, TextureManager.getInstance().getTextureID("frontt")); 
        front.addTriangle(upperRightFront,1,0, lowerLeftFront,0,1, lowerRightFront,1,1,TextureManager.getInstance().getTextureID("frontt")); 
        cube.addChild(front); 
        world.addObject(front);     
        front.setCollisionMode( Object3D.COLLISION_CHECK_SELF); 
         
     // Back...
 
     // Upper...
       
     // Lower...

     // Left...
         
     // Right ...

        cube.strip(); 
        cube.build(); 
        world.addObject(cube); 
        cube.setCulling(false); 
        cube.scale( 0.05f);     
        cube.setCollisionMode( Object3D.COLLISION_CHECK_SELF);


and then , i use the touch event to know which face was triggered when i touched the screen :

public int Pickint( int fX, int fY){ 
     
        //fY = fb.getHeight() - fY;
SimpleVector dir = Interact2D.reproject2D3DWS( cam, fb, fX, fY).normalize();
Object[] res=world.calcMinDistanceAndObject3D(cam.getPosition(), dir, 10000 );
         
        Object3D picked = (Object3D)res[1];   
         
        Object3D picked = (Object3D)res[1]; 
   
        if( picked == null){
       
            return -1; 
       }
       
       
        if( picked.getID() == front.getID()) 
        Log.i("jpctae", "touch front");
        else  if( picked.getID() == back.getID()) 
        Log.i("jpctae", "touch back"); 
        else  if( picked.getID() == upper.getID()) 
        Log.i("jpctae", "touch upper"); 
        else  if( picked.getID() == lower.getID()) 
        Log.i("jpctae", "touch lower");   
        else  if( picked.getID() == left.getID()) 
        Log.i("jpctae", "touch left");   
        else  if( picked.getID() == right.getID()) 
        Log.i("jpctae", "touch right");
         
        return 1; 
    }


However, the questions is :
1- the picked.getID() output only have some respond when i touch the top left corner of every face of cube.
2- or some time the picked always = null

EgonOlsen

The first thing to keep in mind is, that one "face" doesn't mean one polygon. Each side of your cube consists of 2 polygons. In your code, you seem to pick only the first one (or whatever...I'm not sure where you got these IDs from).
The other thing, especially on Android is that the framebuffer coordinates don't match the touch coordinates because of some title bars. More info here: http://www.jpct.net/forum2/index.php/topic,2191.msg16277.html#msg16277

cefengxu

thanks man , even i still can not solve it . i will try again in these day.  :'(

EgonOlsen

It might help to check for Object3D.COLLISION_NONE as first array element to see, if you actually has a collision or not. Just to see if your polygon detection is wrong or simple the picking doesn't return anything.

cefengxu

hi master:

i have spent lots of time to try it but got some strange result.
the faces of cube just valid at some part , as the attached shown.
my test code is every simple , i think it's  correct absolutely:

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {       

        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);


}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {

glViewport(0, 0, width, height);

fb = new FrameBuffer( width, height); // OpenGL ES 1.x constructor

world = new World();

sun = new Light(world);
sun.setIntensity(200, 20, 200);


loadOBJ("cube.obj" , "cube.mtl" , "cube_triangle.png");

cubeColor.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);


world.addObject(cubeColor);


cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.lookAt(cubeColor.getTransformedCenter());


sv.set(cubeColor.getTransformedCenter());
sv.y -= 100;
sv.z -= 100;
sun.setPosition(sv);

MemoryHelper.compact();

}

@Override
public void onDrawFrame(GL10 gl) {

        glClear(GL_COLOR_BUFFER_BIT);
       
if (touchTurn != 0) {
cubeColor.rotateY(touchTurn);
touchTurn = 0;
}

if (touchTurnUp != 0) {
cubeColor.rotateX(touchTurnUp);
touchTurnUp = 0;
}
       
if (actionEventDown_x != -1) {
SimpleVector dir= Interact2D.reproject2D3DWS(cam, fb, (int)actionEventDown_x, (int)actionEventDown_y).normalize();
Object[] res    = world.calcMinDistanceAndObject3D(cam.getPosition(), dir, 10000 /*or whatever*/);
actionEventDown_x = -1;
actionEventDown_y = -1;
if(res[1] != null){
Log.i("jPCT_Picking", "res[0]="+res[0]+" , res[1]="+res[1]);

}
}

fb.clear(back);
world.renderScene(fb);
world.draw(fb);

fb.display();

if (System.currentTimeMillis() - time >= 1000) {
Logger.log(fps + "fps");
fps = 0;
time = System.currentTimeMillis();
}
fps++;

}
   
private InputStream mod = null;
private InputStream mtl = null;
private Object3D cubeColor = null;
private Object3D[] other = null;


public void loadOBJ(String strObjFileName, String strMtlFileName , String strTexFileName) {

try {
mod = this.context.getAssets().open(strObjFileName);
    mtl = this.context.getAssets().open(strMtlFileName);
TextureManager.getInstance().addTexture(strTexFileName, new Texture(context.getAssets().open(strTexFileName)));
} catch (Exception e) {
e.printStackTrace();
}
other = Loader.loadOBJ(mod, mtl,10.0f);
cubeColor = other[0];

}

EgonOlsen

It's most likely caused by what I mentioned above:

Quote
The other thing, especially on Android is that the framebuffer coordinates don't match the touch coordinates because of some title bars.

You have to take the title bar into account when giving the screen coordinates to the reproject-method (you can obtain the dimensions somehow from the Android API, I don't remember the exact call but google will be your friend).

cefengxu

cool ~ got it !
Have to delete Title Bar completely and show the OpenGL Render View only.


EgonOlsen

Quote from: cefengxu on December 14, 2015, 08:03:09 AM
cool ~ got it !
Have to delete Title Bar completely and show the OpenGL Render View only.
That's one way. The other would have been to query the title bar about its dimensions and add the height to the touch coordinates. Anyway, do whatever works best for you...