Author Topic: How to rotate and move 3D object in world space by 2D mouse coordinaes?  (Read 6352 times)

marat

• byte
• Posts: 6
How to rotate and move 3D object in world space by 2D mouse coordinaes?
« on: June 29, 2011, 10:11:03 am »
Hallo!

I want to solve the following problems:
1) How to rotateY() 3D object in world space by 2D mouse coordinates? // 3D object must follow mouse movements
2) How to move 3D object in world space by 2D mouse cooridnates? // 3D object must move in world by mouse click

//Solution 1
SimpleVector mouse3D = Interract2D.reproject2D3DWS(camera, xMouse, yMose).normalize();
float angel = mouse3D.calcAngel(my3Dobject);
my3Dobject.clerRotation();
my3Dobject.rotaYAxis(new SimpleVector(0,1,0), angel);

//Solution 2
SimpleVector mouse3D = Interract2D.reproject2D3DWS(camera, xMouse, yMose).normalize();
Simple direction = mouse3D.calcSub(my3Dobject.getTranslation()); // get direction of 3Dobject
my3Dobject.translate(direction.x+1, 0, direction.z+1);

Sorry for my english.

Thanks!

« Last Edit: June 29, 2011, 10:51:54 am by marat »

Nemetz

• int
• Posts: 53
Re: How to rotate and move 3D object in world space by 2D mouse coordinaes?
« Reply #1 on: June 29, 2011, 11:29:10 am »
Hi!
I'm simply made it in Android version with

marat

• byte
• Posts: 6
Re: How to rotate and move 3D object in world space by 2D mouse coordinaes?
« Reply #2 on: June 29, 2011, 11:48:19 am »
So the solutins is?
SimpleVector mouse3D = Interract2D.reproject2D3DWS(camera, xMouse, yMose).normalize(); // Am correctly use  method to convert 2D mouse coordinates from screen to 3D?
float angel = mouse3D.calcAngel(my3Dobject);
my3Dobject.clerRotation();

i always got positive angel...

EgonOlsen

• Posts: 11884
Re: How to rotate and move 3D object in world space by 2D mouse coordinaes?
« Reply #3 on: June 29, 2011, 01:14:40 pm »
I'm not sure, if this is what you mean, but here's an old and hacky test case of mine. It's for desktop jPCT, but it can easily be ported.

Code: [Select]
`import java.awt.Color;import java.awt.Graphics;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.event.MouseMotionListener;import javax.swing.JFrame;import com.threed.jpct.*;import com.threed.jpct.util.Light;public class MouseFollowDemo  extends JFrame  implements MouseMotionListener, MouseListener{  private static final long serialVersionUID = 1L;  private Graphics g = null;  private FrameBuffer fb = null;  private World world = null;  private Object3D plane = null;  private Object3D ramp = null;  private Object3D player = null;  private Object3D cube2 = null;  private Object3D sphere = null;  private boolean doloop = true;  private boolean pressed = false;  private int mouseX = 320;  private int mouseY = 240;  public MouseFollowDemo()  {    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    pack();    setSize(640, 480);    setResizable(false);    setLocationRelativeTo(null);    setVisible(true);    addMouseMotionListener(this);    addMouseListener(this);    g = getGraphics();  }  @Override  public void mouseMoved(MouseEvent m)  {    mouseX = m.getX();    mouseY = m.getY();  }  @Override  public void mouseDragged(MouseEvent m)  {}  @Override  public void mouseClicked(MouseEvent e)  {}  @Override  public void mouseEntered(MouseEvent e)  {}  @Override  public void mouseExited(MouseEvent e)  {}  @Override  public void mousePressed(MouseEvent e)  {    pressed = true;  }  @Override  public void mouseReleased(MouseEvent e)  {}  private void initStuff()  {    fb = new FrameBuffer(640, 480, FrameBuffer.SAMPLINGMODE_NORMAL);    world = new World();    fb.enableRenderer(IRenderer.RENDERER_SOFTWARE);    ramp = Primitives.getCube(20);    ramp.setAdditionalColor(Color.red);    plane = Primitives.getPlane(20, 10);    plane.setAdditionalColor(Color.GREEN);    sphere = Primitives.getSphere(30);    sphere.setAdditionalColor(Color.CYAN);    sphere.translate(-50, 10, 50);    cube2 = Primitives.getCube(20);    cube2.setAdditionalColor(Color.ORANGE);    cube2.translate(60, -20, 60);    plane.rotateX((float) Math.PI / 2f);    ramp.rotateX((float) Math.PI / 2f);    player = Primitives.getCone(3);    player.rotateX((float) Math.PI / 2f);    player.rotateMesh();    player.clearRotation();    plane.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);    ramp.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);    sphere.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);    cube2.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);    world.addObject(plane);    world.addObject(ramp);    world.addObject(sphere);    world.addObject(cube2);    world.addObject(player);    player.translate(-50, -10, -50);    Light light = new Light(world);    light.setPosition(new SimpleVector(0, -80, 0));    light.setIntensity(40, 25, 22);    world.buildAllObjects();  }  private void lookAt()  {    SimpleVector mousePos = getWorldPosition();    if (mousePos != null)    {      SimpleVector curPos = player.getTranslation();      mousePos = mousePos.calcSub(curPos);      player.setRotationMatrix(mousePos.getRotationMatrix());    }  }  private void relocate()  {    SimpleVector pos = getWorldPosition();    if (pos != null)    {      player.clearTranslation();      player.translate(pos);    }  }  private SimpleVector getWorldPosition()  {    SimpleVector pos = null;    SimpleVector ray = Interact2D.reproject2D3DWS(world.getCamera(), fb, mouseX, mouseY);    if (ray != null)    {      SimpleVector norm = ray.normalize();      float f = world.calcMinDistance(world.getCamera().getPosition(), norm, 1000);      if (f != Object3D.COLLISION_NONE)      {        pos = new SimpleVector();        SimpleVector offset = new SimpleVector(norm);        norm.scalarMul(f);        norm = norm.calcSub(offset);        pos.add(norm);        pos.add(world.getCamera().getPosition());      }    }    return pos;  }  private void doIt()    throws Exception  {    Camera cam = world.getCamera();    cam.moveCamera(Camera.CAMERA_MOVEOUT, 100);    cam.moveCamera(Camera.CAMERA_MOVEUP, 160);    cam.lookAt(plane.getTransformedCenter());    world.getLights().setOverbrightLighting(Lights.OVERBRIGHT_LIGHTING_DISABLED);    while (doloop)    {      lookAt();      if (pressed)      {        relocate();        pressed = false;      }      fb.clear();      world.renderScene(fb);      world.draw(fb);      fb.update();      fb.display(g);      Thread.sleep(10);    }    fb.disableRenderer(IRenderer.RENDERER_OPENGL);    System.exit(0);  }  public static void main(String[] args)    throws Exception  {    MouseFollowDemo cd = new MouseFollowDemo();    cd.initStuff();    cd.doIt();  }}`

marat

• byte
• Posts: 6
Re: How to rotate and move 3D object in world space by 2D mouse coordinaes?
« Reply #4 on: June 29, 2011, 08:31:04 pm »
Thanks EgonOlsen!
It's work 100% very well..

Thanks again...

marat

• byte
• Posts: 6
Re: How to rotate and move 3D object in world space by 2D mouse coordinaes?
« Reply #5 on: July 01, 2011, 09:39:55 am »
Hm!
I still have problems, this example work fine on desktop systems, but on android system emulator it's work not exactly, differences in the mouse coordinates..
Problems with movements,  object does not move exactly (always a distance) when you mouse click.
I don't undesrtand why.

Nemetz

• int
• Posts: 53
Re: How to rotate and move 3D object in world space by 2D mouse coordinaes?
« Reply #6 on: July 01, 2011, 09:44:10 am »
Which code do you use for handling touch events?

Edak

• byte
• Posts: 14
Re: How to rotate and move 3D object in world space by 2D mouse coordinaes?
« Reply #7 on: July 01, 2011, 10:55:17 am »
Here's a method out of my 'directional pad' class, you'll have to edit the centerX and Y accordingly, but given an X and a Y (and the correct center) this will compute a radian to rotate a model by.

Code: [Select]
`public float computeRadian(float x, float y) {                float touchPointX = x - centerX;        float touchPointY = centerY - y;        double a = Math.sqrt(Math.pow(touchPointX, 2) + Math.pow(touchPointY, 2));        double b = a;        double c = Math.sqrt(Math.pow(touchPointX, 2) + Math.pow(touchPointY - a, 2));        Double torsoRotate = new Double(Math.acos((Math.pow(a, 2) + Math.pow(b, 2) - Math.pow(c, 2)) / (2 * a * b)));        //Logger.log("a: "+a+" c: "+c+" Degree: "+Degree);        //Degree *= 0.0174532925; // Number to put in rotateY()        //cos-1((P122 + P132 - P232)/(2 * P12 * P13))        //where P12 is the length of the segment from P1 to P2, calculated by        //sqrt((P1x - P2x)2 + (P1y - P2y)2)        if (x < centerX) {            torsoRotate *= -1;        }        return torsoRotate.floatValue();    }`
So for touch events I do this:

Code: [Select]
`@Override    public boolean onTouchEvent(MotionEvent me) {        if (me.getAction() == MotionEvent.ACTION_DOWN) {            holdType = 0;            windowX = me.getX();            windowY = me.getY();            if (inGame) {                ///If it's in the dpad                //                if (dpadShoot.touched(windowX, windowY)) {                    holdType = 1;                }            }            return true;        }        if (me.getAction() == MotionEvent.ACTION_UP) {                        return true;        }        if (me.getAction() == MotionEvent.ACTION_MOVE) {            if (holdType == 1) {                    Object3D.clearRotation(); //clear the rotation of the model                    Object3D.rotateY(computeRadian(me.getX(), me.getY())); //compute the rotation based on the X and Y given from the touchpad            }            return true;        }        try {            Thread.sleep(15);        } catch (Exception e) {        }        return super.onTouchEvent(me);    }`

Please note, the second bit of code won't work, I just pulled what I have, removed most of it, and put in some sample code. But the first method I posted took me a good solid two days and no sleep to figure out, and it's flawless, so enjoy.
« Last Edit: July 01, 2011, 10:56:55 am by Edak »

marat

• byte
• Posts: 6
Re: How to rotate and move 3D object in world space by 2D mouse coordinaes?
« Reply #8 on: July 01, 2011, 10:58:41 am »
I use this

setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent e) {

switch(e.getAction()) {
case ACTION_MOVE:
xMouse = e.getX();
yMose = e.getY();
break;
}

return true;
}
});

Maybe i should override? ->
@Override  public boolean onTouchEvent
« Last Edit: July 01, 2011, 11:00:46 am by marat »

Edak

• byte
• Posts: 14
Re: How to rotate and move 3D object in world space by 2D mouse coordinaes?
« Reply #9 on: July 01, 2011, 11:04:36 am »
Hey if what you have works so far why change it eh?

EgonOlsen

• Posts: 11884
Re: How to rotate and move 3D object in world space by 2D mouse coordinaes?
« Reply #10 on: July 01, 2011, 04:27:35 pm »
Hm!
I still have problems, this example work fine on desktop systems, but on android system emulator it's work not exactly, differences in the mouse coordinates..
Problems with movements,  object does not move exactly (always a distance) when you mouse click.
I don't undesrtand why.
Because your mouse coordinates are off? Might be that the status bar sets them off by some amount. Given that the mouse coordinates match the frame buffer coordinates, the collision system is pixel perfect. So it have to be your mouse coordinates (or you did some porting error).

marat

• byte
• Posts: 6
Re: How to rotate and move 3D object in world space by 2D mouse coordinaes?
« Reply #11 on: July 01, 2011, 10:11:58 pm »
Hm!
Problem is solved, thanks to everybody

//correct
class X extends activity  {

myGLView.setOnTouchListener(new View.OnTouchListener() {
}

}

//wrong
class X extends activity  {

@Oeverride
public boolean onTouch() {
}

}

Edak

• byte
• Posts: 14
Re: How to rotate and move 3D object in world space by 2D mouse coordinaes?
« Reply #12 on: July 02, 2011, 05:31:41 am »
You say my method is wrong, but why does it work on my phone? I  don't have my code in front of me but could it be variations in phones?