moving selected object with mouse

hello ,
i am very new in openGL, i have faced many problems while i was drawing and selecting and moving objects in 3D
first for selection , i faced a problem then it was solved correctly using processHits way (selection mode ) ,then i moved to the camera , and also it was done correctly , then one thing is left ,
moving the selected object , whatever the camera position is …

let’s suppose we have a vertex v, its current position is :
v.x,v.y,v.z

we select the vertex and we want to move it (of course i am not talking about vertex suppose it is a sphere and v is its center )
now we we move the mouse by dy, and dx, (dy =newmouseposition.y -oldmouseposition.y) and (dx =newmouseposition.x -oldmouseposition.x)
i want to move the object on plane XY
so if i did it this way :

v.x=v.x+dx ;
v.y=v.y+dy;

that is not totally okay cuz after moving a camera with some movements may be the x axis will be on vertical and y for horizantal or the become in an opposite way
i moved to raycast way ,but ait didnt work :

glm::vec3 myglwidget::raycast(int mouse_x, int mouse_y)
{

    GLint viewport[4];
        GLdouble modelview[16];
        GLdouble projection[16];
        GLfloat winX, winY, winZ;
        GLdouble posX, posY, posZ;

        glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
        glGetDoublev( GL_PROJECTION_MATRIX, projection );
        glGetIntegerv( GL_VIEWPORT, viewport );

        winX = (float)mouse_x;
        winY = (float)viewport[3] - (float)mouse_y;

        glReadPixels( mouse_x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );

        gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);

        return glm::vec3(posX, posY, posZ);


}

so what is the solution for this kind of movement ?

hi,
it sounds like u are dealing with problems related to trying to perform transformations along a plane where the viewing plane gets near or on the perpendicular angle to it. I am Assuming you code is working as expected(i.e. bug free). it can get really awkward at this angle: so typically a user would re-orient the camera to a more reasonable angle to manipulated from.

Take a look at Interactive Techniques in Three-dimensional Scenes (Part 1): Moving 3D Objects with the Mouse using OpenGL 2.1 - CodeProject

Although planes are explicitly used as a contrived concept in that link, your use of x, y implies the use of a plane. Does that sound reasonable?
it might help. Do you have any of the usual visual cues: axis widget/grid etc… that help the brain stay “orientated” to what you see in the view port?

The above is a guess.

I think the major problem though is the disorientation you may experience especially at a position where the viewing plane(i.e. your camera) is rolled. Here’s an example:

[ATTACH=CONFIG]1266[/ATTACH]
hopefully you can see what’s happening here:
The camera has been rolled 90 deg around the z axis(ok…it’s y axis in opengl) oh…and slightly pitched 11.5 degrees up(but it actually a y axis yaw(because of the roll!) confusing? you bet. So now if you continue with your x, y code, left/right and up/down mouse movements are switched, not in 3d space, but only on the viewing plane (to the users detriment). So you are asking for a solution. There really isn’t one. Even if you built in more visual cues than the ones illustrated to help the user stay mentally orientated to the 3d space, its rarely a useful way to move objects (making cinematic tracking videos where rolling becomes a special effect could be a exception… others?). Otherwise, it is typical to maintain an orbiting camera around the objects you are moving in a more intuitive manner as seen in modelling packages like maya/max etc. What would you use it for? do you have something in mind?

Ahhh… the image no good, too small, is not effective. its a screen shot from a little app that interactively illustrates this kind of stuff in real time. send me an email and i’ll reply by sending the zipped up app to you if you wish.

Using the code
In this example I use MFC wizard. All my code was written on CView.

Add variables:

Hide Copy Code
private:
GLdouble gldAspect;
GLsizei glnWidth, glnHeight;
HGLRC hRC;
Cube cube[4];
double r;
Cube is defined in MyOpenGL.h.

Use “class wizard” for message map: WM_CREATE, WM_DESTROY, WM_EARSEBKGND, WM_LBUTTONDOWN, WM_PAINT, WM_SIZE, WM_TIMER. oneplus 2 case

On another article in CodeProject about OpenGL you can see the code for WM_SIZE and WM_PAINT, WM_CREATE (I use the code again! Thanks to the owner’s code!).

Additionally, on WM_CREATE, init for some variables and start the timer for animation.

Hide Copy Code
int CTry_OpenGLView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;

 // TODO: Add your specialized creation code here
 hRC=SetUpOpenGL(m_hWnd);
 for(int i=0;i<4;i++) cube[i].x=i*2-3;
 r=0;
 SetTimer(1000,100,NULL);

 return 0;

}
Of course, kill timer in OnDestroy().

Timer:

Hide Copy Code
void CTry_OpenGLView::OnTimer(UINT nIDEvent)
{
r+=5;
if(r>=360) r=0;
RedrawWindow();

 CView::OnTimer(nIDEvent);

}
In OnEraseBkgnd: delete all (if not, the screen will “flick”).

And now, the code to pick an object:

Hide Shrink Copy Code
void CTry_OpenGLView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
GLuint selectBuf[BUFSIZE];
GLint hits;
GLint viewport[4];

 HDC hDC = ::GetDC(this->m_hWnd);
 wglMakeCurrent(hDC,hRC);

glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (BUFSIZE, selectBuf);

glRenderMode(GL_SELECT); // Enter the SELECT render mode
glInitNames();
glPushName(-1);

glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
gluPickMatrix((GLdouble) point.x, 
      (GLdouble) (viewport[3] - point.y), 
      5.0, 5.0, viewport);
gluPerspective(30.0,gldAspect,1.0,20.0);
glMatrixMode(GL_MODELVIEW);
PaintScreen(GL_SELECT);//function paint the objects.
glPopMatrix ();
glFlush ();

hits = glRenderMode (GL_RENDER);

 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glViewport(0,0,glnWidth,glnHeight);
 gluPerspective(30.0,gldAspect,1.0,20.0);

 /*for(int i=0;i<hits;i++)
 {
      cube[selectBuf[3+i*4]].selected= 
         !cube[selectBuf[3+i*4]].selected;
 }//select all (include the hide object)!
 */
 if (hits)
 {
      int n=0;double minz=selectBuf[1];
      for(int i=1;i<hits;i++)
      {
           if (selectBuf[1+i*4]<minz) 
             {n=i;minz=selectBuf[1+i*4];}
      }
      cube[selectBuf[3+n*4]].selected=
          !cube[selectBuf[3+n*4]].selected;
 }//only select the object we see (nearest object)!

 wglMakeCurrent( NULL, NULL );
::ReleaseDC( this->m_hWnd, hDC );

 CView::OnLButtonDown(nFlags, point);

}