Touch 3D object ArToolKitJpctBaseLib

625 Views Asked by At

I found an adaptation of ARToolKit + jpct + android:

https://github.com/plattysoft/ArToolKitJpctBaseLib

I've got draw various 3D objects on the screen. But now I have the problem: I need to touch them I saw this tutorial: http://www.jpct.net/wiki/index.php?title=Picking But my class is something different, is very abstracted and simple and I'm a newbie ..

This is the mainClass, I don't found my framebuffer...

import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.FrameLayout;
import android.widget.Toast;


import com.threed.jpct.Loader;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;

import org.artoolkit.ar.jpct.ArJpctActivity;
import org.artoolkit.ar.jpct.TrackableLight;
import org.artoolkit.ar.jpct.TrackableObject3d;

import java.io.IOException;
import java.util.List;

public class RealidadAumentada extends ArJpctActivity{
    private Object3D astronauta = null;
    private TrackableObject3d cubo = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

    }

/**
 * Use the FrameLayout in this Activity's UI.
 */
@Override
protected FrameLayout supplyFrameLayout() {
    return (FrameLayout)this.findViewById(R.id.mainLayout);
}

public void configureWorld(World world) {
    world.setAmbientLight(150, 150, 150);

}

protected void populateTrackableObjects(List<TrackableObject3d> list) {
    Object3D astronauta2 = null;

    try {
        cubo = new TrackableObject3d("single;Data/patt.hiro;80", getCube());
        //astronauta2 = getAstronauta2());
        astronauta = getAstronauta();
        astronauta.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
    } catch (IOException e) {
        e.printStackTrace();
    }

    TrackableLight light = new TrackableLight();
    light.setIntensity(0, 0, 255);
    light.setPosition(new SimpleVector(0, 0, 100));
    cubo.addLight(light);

    cubo.addChild(astronauta);

    list.add(cubo);

}

private Object3D getCube() throws IOException {
    int scale = 40;
    Object3D object3D = Primitives.getCube(scale);
    // Cubes in jpct are rotated by 45 degrees when created.
    object3D.rotateY((float) Math.PI / 4);
    object3D.setOrigin(new SimpleVector(0, 0, scale));
    return  object3D;
}

    private Object3D getAstronauta() throws IOException {
        int scale = 40;
        Object3D[] astronaut = Loader.load3DS(getAssets().open("astronaut1.3ds"), 5);
        astronaut[0].setOrigin(new SimpleVector(0, 0, 270));

        return  astronaut[0];
    }


    This method doesnt work
    public boolean onTouchEvent(MotionEvent me) {
        if (me.getAction() == MotionEvent.ACTION_DOWN) {
            Toast.makeText(this, cubo.getXAxis().toString()+"      "+String.valueOf(me.getX()),2000).show();
           //   Toast.makeText(this,String.valueOf(cubo.getCenter()),2000).show();
            return true;
        }
          ....
}
3

There are 3 best solutions below

0
On

This is my solution:

patron = new TrackableObject3d("single;Data/patt.hiro;80");

Patron is a trackable object, is the example patt hiro.

 objeto.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
            patron.addChild(objeto);
            if (mWorld.getObjectByName(objeto.getName())==null)
                mWorld.addObject(objeto);

patron.addChild because I have many objects in the screen. objeto.setCollisionMode is a jcpt function that makes the object collisionable.

The next step: Touch screen (more info in internet)

    public boolean onTouch(View v, MotionEvent event) {

Next step:

fb is the frameBuffer. xpos and ypos are the 2Dcoordinates. Then, You have to draw a raytrace from xpos and ypos to get the 3D coordinates. objeto is the object you're touching.

case MotionEvent.ACTION_UP:

     int xpos = (int) event.getX();
     int ypos = (int) event.getY();
     SimpleVector dir = Interact2D.reproject2D3DWS(mWorld.getCamera(), fb, xpos, ypos);
     SimpleVector norm = dir.normalize();
     Object[] res = mWorld.calcMinDistanceAndObject3D(mWorld.getCamera().getPosition(), norm, 1000);
     Object3D objeto = (Object3D) res[1];
     float f = mWorld.calcMinDistance(mWorld.getCamera().getPosition(), norm, 1000);

     if (f != Object3D.COLLISION_NONE) {
         //Interact with object
         String nombre = objeto.getName(); 
         Vibrator vib = (Vibrator) getSystemService(VIBRATOR_SERVICE);
         vib.vibrate(100);
     }
2
On

I don't see you setting the touch listener anywhere, overriding that method works on the GLSurfaceView class, not on the Activity.

You could set a touch listener to the frame layout (R.id.mainLayout) on creation after setting the content view.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    findViewById(R.id.mainLayout).setOnTouchListenr(this);

}

@Override
public onTouch(View v, MotionEvent event) {
  // Your implementation of touch goes here, not in onTouchEvent
}

The whole idea of the library you are using is to encapsulate all the boilerplate code, such as creating a Renderer which is going to be the same for almost every app.

If you want to access the SurfaceView and extend it to implement that method there, you can do it overwriting this part: https://github.com/plattysoft/ArToolKitJpctBaseLib/blob/master/ArJpctBaseLib/src/main/java/org/artoolkit/ar/base/ARActivity.java#L217

0
On

Solved ! I spent many hours but I finally got what I wanted. Draw several 3D objects on a ARToolKit(Android) marker and then click on each of them.

Thanks for the help