Log in or register to post comments

Touch Objects

May 30, 2011 - 6:38am #1

please help me, i'm develope imagetargets app into my own app..my own app render a hospital building when my camera detect several marker..my problem is, i want make that when i touch the object from my device screen, "details" button appear ( like dominoes app do), and when i touch the "details" button, pop up window appear and show the information about my object..i'm not that expert with java and c++..can anyone help me please??

regards,

Gyan

Re: Touch Objects

October 25, 2011 - 7:24pm #25

Please see my response in this thread: http://ar.qualcomm.at/node/2001068

That will help you determine whether a touch lands inside the target, and where. If you want to perform selection on 3D objects you'll have to pick apart more of the Dominoes code. The dominoNormals and dominoTransformedVerticesA variables are used to describe object aligned bounding boxes that surround the 3D objects (in the case of that sample, the dominoes). You'll have to define similar boxes around your 3D objects to use that code. You may be better off determining where the touch landed on the target and doing distance checks to your objects, it would be a simpler starting point.

- Kim

Re: Touch Objects

October 25, 2011 - 9:59am #24

hi kim ... i want to get the tap event on teapot ....as suggested by you in above posts i was trying to put the dominoes code in ImageTargets sample.... i have some doubts

what should be touch1.tapX, touch1.tapY ??

JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_nativeTouchEvent(JNIEnv* , jobject, jint actionType, jint pointerId, jfloat x, jfloat y)
{
	LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_nativeTouchEvent");
	TouchEvent* touch1;
	touch1->x = x;
        touch1->y = y;
	
	QCAR::Vec3F intersection, lineStart, lineEnd;
        projectScreenPointToPlane(QCAR::Vec2F(touch1.tapX, touch1.tapY), QCAR::Vec3F(0, 0, 0), QCAR::Vec3F(0, 0, 1), intersection, lineStart, lineEnd);
        
        
        
        QCAR::Matrix44F transform = SampleMath::Matrix44FIdentity();
		float* transformPtr = &transform.data[0];
		SampleUtils::translatePoseMatrix(0.0f,0.0f, 3.0f, transformPtr);//&modelViewMatrix.data[0]
		SampleUtils::scalePoseMatrix(5.0f, 5.0f, 5.0f, transformPtr);
		
		bool hit = checkIntersectionLine(transform, lineStart, lineEnd);
        if (hit)
		{
		    LOG(" ******* Tap *******");
		}
	
}

i have copied the projectScreenPointToPlane and linePlaneIntersection method as it is

what should dominoNormals, dominoTransformedVerticesA ??

bool
checkIntersectionLine(QCAR::Matrix44F transformA, QCAR::Vec3F pointA, QCAR::Vec3F pointB)
{
    // Use the separating axis theorem to determine whether or not
    // the line intersects the object-oriented bounding box
    
    transformA = SampleMath::Matrix44FTranspose(transformA);
    QCAR::Vec3F lineDir = SampleMath::Vec3FSub(pointB, pointA);
    
    QCAR::Vec3F normalA1 = SampleMath::Vec3FTransformNormal(dominoNormals[0], transformA);
    QCAR::Vec3F normalA2 = SampleMath::Vec3FTransformNormal(dominoNormals[1], transformA);
    QCAR::Vec3F normalA3 = SampleMath::Vec3FTransformNormal(dominoNormals[2], transformA);
    
    QCAR::Vec3F crossA1 = SampleMath::Vec3FCross(normalA1, lineDir);
    QCAR::Vec3F crossA2 = SampleMath::Vec3FCross(normalA2, lineDir);
    QCAR::Vec3F crossA3 = SampleMath::Vec3FCross(normalA3, lineDir);
    
    for (int i = 0; i < 8; i++) {
        dominoTransformedVerticesA[i] = SampleMath::Vec3FTransform(dominoBaseVertices[i], transformA);
    }
    
    if (isSeparatingAxisLine(normalA1, pointA, pointB)) return false;
    if (isSeparatingAxisLine(normalA2, pointA, pointB)) return false;
    if (isSeparatingAxisLine(normalA3, pointA, pointB)) return false;
    
    if (isSeparatingAxisLine(crossA1, pointA, pointB)) return false;
    if (isSeparatingAxisLine(crossA2, pointA, pointB)) return false;
    if (isSeparatingAxisLine(crossA3, pointA, pointB)) return false;
    
    return true;
}

plz chk the above code and let me know if its ok

Re: Touch Objects

June 22, 2011 - 3:10pm #23

As I mentioned in your other thread, I'd guess that applicationContext is null.

I highly recommend learning how to use the Eclipse debugger for your Java code. You can add a breakpoint to the onClick method by right-clicking on the gray margin to the left of the line of code. Then simply run your app by choosing Run > Debug. Code execution will stop at that point and you can step through line by line. Look for a tutorial, there are lots of resources out there!

- Kim

Re: Touch Objects

June 22, 2011 - 8:02am #22

this is my logcat details Kim, i really dont know what wrong with my code :

06-22 22:00:32.075: ERROR/AndroidRuntime(14337): FATAL EXCEPTION: main
06-22 22:00:32.075: ERROR/AndroidRuntime(14337): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at android.view.ViewRoot.setView(ViewRoot.java:509)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at android.app.Dialog.show(Dialog.java:241)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at org.ARmap.GUIManager$2.onClick(GUIManager.java:136)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at android.view.View.performClick(View.java:2408)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at android.view.View$PerformClick.run(View.java:8816)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at android.os.Handler.handleCallback(Handler.java:587)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at android.os.Handler.dispatchMessage(Handler.java:92)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at android.os.Looper.loop(Looper.java:123)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at android.app.ActivityThread.main(ActivityThread.java:4633)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at java.lang.reflect.Method.invokeNative(Native Method)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at java.lang.reflect.Method.invoke(Method.java:521)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
06-22 22:00:32.075: ERROR/AndroidRuntime(14337):     at dalvik.system.NativeStart.main(Native Method)
06-22 22:00:32.075: WARN/ActivityManager(173):   Force finishing activity org.ARmap/.ImageTargets

Re: Touch Objects

June 21, 2011 - 7:03pm #21

What sort of error are you seeing in the logs? When the app crashes in the Java code you should get some nice details, including error messages and line numbers.

- Kim

Re: Touch Objects

June 21, 2011 - 7:32am #20

Kim, i want my button show a dialog when i click on the delete button, i replace the code in GUImanager.java into this :

deleteButton = (Button) overlayView.findViewById(R.id.delete_button);
        deleteButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {

               AlertDialog.Builder aboutDialog = new AlertDialog.Builder(applicationContext);
            			aboutDialog.setMessage("test");	
            			
            			aboutDialog.setNegativeButton("test", new DialogInterface.OnClickListener() {
            				public void onClick(DialogInterface dialog, int id) {
            					dialog.dismiss();
            				}
            			});
            			AlertDialog aboutAlert = aboutDialog.create();
            			aboutAlert.setTitle("test");
            			aboutAlert.show();

            }
        });

but the app force close when i click the button..have i do something wrong??

Re: Touch Objects

June 20, 2011 - 9:25pm #19

sorry, i make the mistake on the code before, i write the code to call the showdeletebutton like this :

void showDeleteButton();

i fix the code into this :

showDeleteButton();

sorry to bother you KIM..

regards,

Gyan

Re: Touch Objects

June 20, 2011 - 6:47pm #18

In the Dominoes project the showDeleteButton() and hideDeleteButton() methods are located in the DominoesRenderer java class. Have you added these methods? Try printing something to the log from these methods to make sure they are getting called correctly (or use breakpoints!)

- Kim

Re: Touch Objects

June 20, 2011 - 8:33am #17

this is my JNI call to java :

void
showDeleteButton()
{
    // For this application, buttons are handled by the Android SDK
    // Use the environment and class stored in initNativeCallback
    // to call a Java method that shows the delete button
    jmethodID method = javaEnv->GetMethodID(javaClass, "showDeleteButton", "()V");
    javaEnv->CallVoidMethod(javaObj, method);
}

void
hideDeleteButton()
{
    // For this application, buttons are handled by the Android SDK
    // Use the environment and class stored in initNativeCallback
    // to call a Java method that hides the delete button
    jmethodID method = javaEnv->GetMethodID(javaClass, "hideDeleteButton", "()V");
    javaEnv->CallVoidMethod(javaObj, method);
}

and this is my GUImanager.java :

mainActivityHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case SHOW_DELETE_BUTTON:
                    if (deleteButton != null) {
                        deleteButton.setVisibility(View.VISIBLE);
                    }
                    break;
                    
                case HIDE_DELETE_BUTTON:
                    if (deleteButton != null) {
                        deleteButton.setVisibility(View.INVISIBLE);
                    }
                    break;
                    
                    case DISPLAY_INFO_TOAST:
                    	String text = (String) msg.obj;
                        int duration = Toast.LENGTH_LONG;
                        Toast toast = Toast.makeText(applicationContext, text, duration);
                        toast.show();
                        break;
                }
            }
        };
    }
    
    public void initButtons()
    {
    	if (overlayView == null)
            return;
        
        startButton = (ToggleButton) overlayView.findViewById(R.id.start_button);
        startButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                if (((ToggleButton) v).isChecked()) {
                    nativeStart();
                } else {
                    nativeReset();
                }
            }
        });
        
       
        
        deleteButton = (Button) overlayView.findViewById(R.id.delete_button);
        deleteButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                nativeDelete();
            }
        });
    }
    
    
    /** Clear the button listeners. */
    public void deinitButtons()
    {
        if (overlayView == null)
            return;
        
        //startButton.setOnClickListener(null);
        //clearButton.setOnClickListener(null);
        deleteButton.setOnClickListener(null);
        
        //startButton = null;
        //clearButton = null;
        deleteButton = null;
    }

i paste the interface_overlay from dominoes and edit the file so that i only have delete button

note :
when i set deletebutton to visible in interface_overlay, the deletebutton appear everytime when the app start altough i do not tap on the object, but when i set to invisible, the deletebutton doesnt appear when i tap on the object..

Re: Touch Objects

June 19, 2011 - 8:43pm #16

What does your JNI call (the call from native to Java) look like? Make sure you are using a valid Java environment, and make sure the method exists in the class you are calling up to. Are you seeing any errors in the log?

Note the interface_overlay.xml file in the Dominoes project, make sure you have something similar. Then try using debug breakpoints or print statements in your Java code to trace what happens when you call the showDeleteButton() Java method.

- Kim

Re: Touch Objects

June 19, 2011 - 5:48am #15

Kim, i want a delete button appear after i tap the object i add this code in imagetargets.cpp :

void handleTapEvent()
{
    //playSoundEffect(0);
    //displayMessage("Objek Disentuh");
    QCAR::Vec3F intersection, lineStart, lineEnd;
    projectScreenPointToPlane(tapCoords, QCAR::Vec3F(0, 0, 0), QCAR::Vec3F(0, 0, 1), intersection, lineStart, lineEnd);
    
    LOG("intersection: %f, %f, %f", intersection.data[0], intersection.data[1], intersection.data[2]);
    
    QCAR::Matrix44F transform = SampleMath::Matrix44FIdentity();
    float* transformPtr = &transform.data[0];
    SampleUtils::translatePoseMatrix(10.0f, 0.0f, kObjectScale, transformPtr);
    SampleUtils::scalePoseMatrix(25.f, 25.f, 25.f, transformPtr);
    
    bool hit = checkIntersectionLine(transform, lineStart, lineEnd);
    if (hit)
    {
        LOG("hit");
        // tap touched the object
        playSoundEffect(0);

        QCAR::State state = QCAR::Renderer::getInstance().begin();
        // Did we find any trackables this frame?
            for(int tIdx = 0; tIdx < state.getNumActiveTrackables(); tIdx++)
            {
                // Get the trackable:
                const QCAR::Trackable* trackable = state.getActiveTrackable(tIdx);
                if (strcmp(trackable->getName(), "shika1") == 0){
                	void showDeleteButton();
                        }
                else if (strcmp(trackable->getName(), "shika2") == 0){
                	void showDeleteButton();
                		}
            }
    }
    else{

    	void hideDeleteButton();
    }
}

and this code into imagetargets.java :

if (mGUIManager != null)
        {
            mGUIManager.deinitButtons();
        }

if (mGUIManager != null)
        {
            mGUIManager.initButtons();
        }

i also add the GUI manager from dominoes..and modified the imagetargetsrenderer.java like dominoesrenderer.java..my code build successfully..i run my app, but when i tap the object, the delete button doesn't appear..

Re: Touch Objects

June 15, 2011 - 3:01pm #14

Yeah, i add all the code you tell me in

http://ar.qualcomm.at/node/2000521

the build get no error. but when i start the application, i have the same problem, like i said before, everywhere i touch, even when the trackable is not detected, the nativeTapEvent in native is run..

I alse send my full code to qcar-support@qualcomm.com..can you take a look on my code Kim??

Re: Touch Objects

June 14, 2011 - 11:52am #13
Quote:

but my method works when i touch the screen, not only when i touch the object..why did that happen??

Are you checking for intersections using the checkIntersectionLine method, as we discussed in the earlier posts? Make sure that you set the correct bounding box for your object (using translate and scale, see the earlier code snippets).

Quote:

my app force close when i start it, i have import the GUImanager from dominoes, and create interface_overlay.xml myself, like the dominoes..

Make sure you have created the mGUIManager before using it:

mGUIManager = new GUIManager(getApplicationContext());

- Kim

Re: Touch Objects

June 13, 2011 - 7:28am #12

Hei thank you very much Kim, it works perfectly..i edited the method NativeTapEvent(). but my method works when i touch the screen, not only when i touch the object..why did that happen??

when i touch the object, i want my app display the button like dominoes, i follow the code to call the button. but i have the problem here :

 addContentView(mGUIManager.getOverlayView(), new LayoutParams(
                                            LayoutParams.FILL_PARENT,
                                            LayoutParams.FILL_PARENT));

my app force close when i start it, i have import the GUImanager from dominoes, and create interface_overlay.xml myself, like the dominoes..

Re: Touch Objects

June 5, 2011 - 4:00pm #11

I suggest making your life easier and only sending the tap event to native. That will cut out a lot of code copying from the Dominoes sample (and hopefully a lot of your compilation errors). Here's how to send a tap event to native:

ImageTargets.java

private GestureDetector mGestureDetector;

protected void onCreate(Bundle savedInstanceState)
{
    ...
    
    mGestureDetector = new GestureDetector(this, new TapGestureListener());
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
    if (mGestureDetector.onTouchEvent(event))
        return true;
    else
        return false;
}

private native void nativeTapEvent(float tapX, float tapY);

class TapGestureListener extends GestureDetector.SimpleOnGestureListener
{
    @Override
    public boolean onSingleTapUp(MotionEvent ev)
    {
        nativeTapEvent(ev.getX(), ev.getY());
        return true;
    }
}

ImageTargets.cpp

JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_nativeTapEvent(JNIEnv *, jobject, jfloat tapX, jfloat tapY)
{
    LOG("tap: %f, %f\n", tapX, tapY);
}

- Kim

Re: Touch Objects

June 4, 2011 - 2:23am #10

You absolutely right Kim, i just wanna my a button appear if i tap on the object ( like dominoes app, the delete button appear if user tap on the domino object ),i dont need the method to render object due to my finger slide up or down.. so, i try to follow your instruction above, but i have error while ndk-build. i dont understand, too many error i have..

i also send my file to

take a look for my code.. help me..i beg you..

Re: Touch Objects

June 3, 2011 - 7:25am #9

Start with getting the touch events from Java to native. The Dominoes project does this in a fairly complex way so it can handle multi-touch and dragging, you may want to simplify it. It sounds like you may just need the results of a tap, so capture the tap using onTouchEvent(MotionEvent event) in ImageTargets.java and send the coordinates to native.

Once you have the tap coordinates in native, you can project them to the image target plane using projectScreenPointToPlane(). For checkIntersectionLine(), you just need a transform that describes the bounds of the object you want to pick.

QCAR::Vec3F intersection, lineStart, lineEnd;
projectScreenPointToPlane(QCAR::Vec2F(tapX, tapY), QCAR::Vec3F(0, 0, 0), QCAR::Vec3F(0, 0, 1), intersection, lineStart, lineEnd);

QCAR::Matrix44F transform = SampleMath::Matrix44FIdentity();
float* transformPtr = &transform.data[0];
SampleUtils::translatePoseMatrix(objectPosX, objectPosY, objectPosZ, transformPtr);
SampleUtils::scalePoseMatrix(objectWidth, objectDepth, objectHeight, transformPtr);

bool hit = checkIntersectionLine(transform, lineStart, lineEnd);
if (hit)
{
    // tap touched the object
}

The only other trick is that projectScreenPointToPlane depends on two globally defined variables, inverseProjMatrix and modelViewMatrix.

global

QCAR::Matrix44F inverseProjMatrix;
QCAR::Matrix44F modelViewMatrix;

Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_startCamera

const QCAR::Tracker& tracker = QCAR::Tracker::getInstance();
const QCAR::CameraCalibration& cameraCalibration = tracker.getCameraCalibration();
projectionMatrix = QCAR::Tool::getProjectionGL(cameraCalibration, 2.0f, 2000.0f);
inverseProjMatrix = SampleMath::Matrix44FInverse(projectionMatrix);

Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargetsRenderer_renderFrame

const QCAR::Trackable* trackable = state.getActiveTrackable(tIdx);
modelViewMatrix = QCAR::Tool::convertPose2GLMatrix(trackable->getPose());

- Kim

Re: Touch Objects

June 3, 2011 - 5:23am #8

Ok Kim, next, please tell me the details..what code/method i must export and edit form dominoes app into imagetargets app to picking object beside updatePickingTransform(), projectScreenPointToPlane(), and checkIntersectionLine() method..i really have to finish my problem about picking object completely..my thesis really depends on it..

Re: Touch Objects

June 2, 2011 - 11:33am #7

I don't have any suggestions, you'll have to search for Android OpenGL ES game engines / physics engines. Integrating these won't be trivial either, but can be worth the effort for large projects.

- Kim

Re: Touch Objects

June 1, 2011 - 11:34pm #6

Kim, can you tell me the other game engine or tool that integrated with QCAR??because my device crash when start QCAR-Unity project..

Re: Touch Objects

June 1, 2011 - 12:44pm #5

InitNativeCallBack is called from the DominoesRenderer.java class. If you wanted to use something similar for the ImageTargets project you would need to change the native method signature from this:

Java_com_qualcomm_QCARSamples_Dominoes_DominoesRenderer_initNativeCallback(JNIEnv* env, jobject obj)

to this:

Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargetsRenderer_initNativeCallback(JNIEnv* env, jobject obj)

Then you could call it from the ImageTargetsRenderer.java class.

I can't show you how to move all the picking code from Dominoes to ImageTargets, there's a lot to it. You might try to tackle it by feature, e.g. start with adding touch support to the ImageTargets project (get the touch coordinates in native). Spend some time working through the JNI calls to communicate back and forth between Java and native. It's a lot to learn, but it's necessary if you want to build your own Android NDK applications.

- Kim

Re: Touch Objects

June 1, 2011 - 10:48am #4

Can you provide me a code i can use to pick the object in imagetargets.cpp ( like you said above )??dominoes.cpp use InitNativeCallBack ini native code, its hard to understand for me..because the imagetargets.cpp didn't use that method..

Re: Touch Objects

May 31, 2011 - 12:38pm #3

Touching an object (i.e. picking) is a non-trivial 3D problem. The Dominoes sample uses object-oriented bounding boxes and does a line/box intersection test. There are a few steps to use this code:

1) Define a bounding box transform for your object. See the updatePickingTransform() method, this creates a matrix that transforms a unit cube into the desired bounding box.

2) Use the projectScreenPointToPlane() method to get the start and end points of a line from the touch point into the scene.

3) Intersect the line with the bounding box using the checkIntersectionLine() method. This returns true if you hit the object.

Of course this depends on a lot of other code set up in the Dominoes sample, e.g. the touch handling code. There's a lot to it, which is why many people will choose to integrate a game engine or physics engine, or use a tool like Unity.

- Kim

Re: Touch Objects

May 31, 2011 - 7:49am #2

Maybe its to difficult, can someone tell me how to display a button after i touch an object??like dominoes sample..i try harder to understand the code in dominoes, but i cant..

Log in or register to post comments