while dragging, object moves faster than finger

Started by sisu, June 24, 2012, 03:41:06 PM

Previous topic - Next topic

sisu

Hi

I have a problem with touch gestures using jPCT-AE. When I want to drag an Object3D, the object moves faster than my finger. I use following code:

public boolean onTouchEvent(MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_DOWN) {
xpos = me.getX();
ypos = me.getY();
return true;
}

if (me.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
                        dragging = false;
moveX = 0; //used for dragging
moveY = 0; //used for dragging
return true;
}

if (me.getAction() == MotionEvent.ACTION_MOVE) {
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;

              xpos = me.getX();
ypos = me.getY();

dragging = true;
moveX = xd; //used for dragging
moveY = yd; //usedf or dragging
return true;
}

try {
Thread.sleep(15);
} catch (Exception e) {
// No need for this...
}

return super.onTouchEvent(me);
}

public void onDrawFrame(GL10 gl) {
        if(dragging){
cube.translate(0, moveY, 0);
cube.translate(moveX, 0, 0);
dragging = false;
        }

}



Any suggestions on how I can keep the object under my finger?

PS: I'm fairly new to this library, but I really like it so far!! Great job!

EgonOlsen

That doesn't work. because you are mixing 2d screen coordinates (your touch coordinates) with 3d world coordinates (your actual translation). If the object to be dragged lies within the xy-plane (i.e. it has constant z), something like this should work:


SimpleVector pos= Interact2D.reproject2D3D(camera, buffer, touchX, touchY, constantZ);
pos.matMul(camera.backMatrix.invert3x3());
obj.clearTranslation();
obj.translate(pos);

sisu

Hey, thanks for your answer, but I couldn't fix it. I tried several solutions in the forum the last few days but none worked out for me. In the attachment I put the HelloWorld file from the wiki with your proposed solution added. Is there something missing? (I only changed the code in the "me.getAction() == MotionEvent.ACTION_MOVE")

[attachment deleted by admin]

EgonOlsen

The 1f in your call to SimpleVector pos= Interact2D.reproject2D3D(cam, fb, (int)me.getX(), (int)me.getY(), 1f); is not correct. You have to use the z-plane in camera space in which the object will move. In this case (as the object is located at the origin but the camera has moved 50 unit away from it), this should be 50f instead.

sisu

Hi, thanks for you quick response. I changed the value to 50f, but when I drag the cube, it jumps to another z-level I guess. The value of cam.getPosition().z is indeed (-)50 which is logical because when loading the cube it moves out the camera 50f.

[attachment deleted by admin]

EgonOlsen

My bad. The z=50 will be stored in the pos vector, but you don't want to apply it to the translation. Just add


pos.z=0f;


after calculating pos and it should work.

sisu

#6
Hi, thank you very much!! It works now and I am starting to understand the interaction between the different coordinate systems.

I've got another problem though: I'd like to save a snapshot of the framebuffer onto the phone when the user touches the screen but I get a 'called unimplemented OpenGL ES API' error and a black image is saved. I use following code:

if (me.getAction() == MotionEvent.ACTION_DOWN) {
Bitmap image = null;
if (fb != null){
image = Bitmap.createBitmap(fb.getPixels(), fb.getWidth(), fb.getHeight(), Bitmap.Config.ARGB_8888);
       
                //Stuff to store the image
String extr = Environment.getExternalStorageDirectory().toString() + File.separator + "Deco";
String fileName = new SimpleDateFormat("'Snapshot_'yyyy'-'MM'-'dd'_'hh':'mm':'ss'.jpg'").format(new Date());
String filePath = extr + "/" + fileName;
File myPath = new File(extr, fileName);

try {
FileOutputStream fos = new FileOutputStream(myPath);
image.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
//MediaStore.Images.Media.insertImage(getContentResolver(), b, "Screen", "screen");
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
               // end stuff to store image
}
return true;
}


When I use this code in the onDrawFrame(GL10 gl) of the MyRenderer class after following lines, it works.
fb.clear(back);
world.renderScene(fb);
world.draw(fb);


Do you know how to solve this? In the documentation is also written that it is recommended to use getPixels() after update(), but it seems that there is no update method for the jPCT-AE version.

EgonOlsen

Opps, that's a documentation flaw...however, if that exception occurs, it seems like your device doesn't support to grab the pixels from the FrameBuffer. Which device and which version of Android is that?

sisu

I don't think my device doesn't support it because I can use the getPixels() method in the onDrawFrame(GL10 gl) and take a snapshot with no problem, It only doesn't work if I use it in the onTouchEvent (which is outside the 'MyRenderer implements GLSurfaceView.Renderer' class).

The device I use is a Samsung Galaxy Tab 8.9 (WiFi) P7310 and I am working with Android 3.0 platform.

sisu

Okay, I managed to take a snapshot with a hackish way: I set a boolean to true in the onTouchEvent and in the onDraw method I check the boolean and if true take a snapshot. I think I can't access the framebuffer in the onTouchEvent because it is running in another thread or something. If you have a beter solution, I'd like to hear it :)

EgonOlsen

Quote from: sisu on June 30, 2012, 04:50:10 PM
Okay, I managed to take a snapshot with a hackish way: I set a boolean to true in the onTouchEvent and in the onDraw method I check the boolean and if true take a snapshot. I think I can't access the framebuffer in the onTouchEvent because it is running in another thread or something. If you have a beter solution, I'd like to hear it :)
That's not hackish, that's the way you are supposed to do it. You can't access gl related stuff from outside the render thread.

sisu

Ow I see. I appreciate the effort you put in jPCT, you should put a donate button on the website :)