Picking and transformation Help

Started by
10 comments, last by Isoprog 14 years, 7 months ago
hi, i am making an application where i have created a cube. now i want to pick it with mouse and transform it with mouse. can someone show me how to do it. my application is windows based(not MFC). kindly don't use glut to mouse pick. thank you for reply. regards, isoprog
Advertisement
Quote:Original post by Isoprog
now i want to pick it with mouse and transform it with mouse.

I don't have the answer, but thought I'd add some questions to help facilitate more useful responses:

1) Does it matter where the cube is clicked, or will any point on the cube work?
2) Is the cube stationary? Is it affected by physics?
3) What specific transformations are you looking to perform?
you disable texturing and lighting, you set a unique color for the cube (lets say 255, 0, 0)

Find where the mouse is and calculate a small rectangle (in screen space) around it. Set glScissor to that rectangle (no point rendering the whole thing, just the bit you are clicking). Render your scene (with textures andlighitng off and unique colors for the objects you are clicking).

Get the pixels you just rendered (again, you only need the pixels in the small rectangle around the moouse. Either use a fbo or glReadPixels from the back buffer). Check what color the pixels were, if they were 255, 0, 0 then the cube was clicked, if not somehting else was clicked.

If you have many pixels rendered then you can either work out the most common pixel color and use that, or the first non black one or some other method (I render just one pixel and it works fine).

Not sure about transformthing things with the mouse, I've only done the most basic of transforms.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

thanks,
in my application there are no physics, just a simple cube which i want to pick and transform using either mouse or an editor(directly putting the value) or using arrow keys. i have tryed many ways but nothing is working(not transforming, only picking). i want picking becouse my apllication creates as many as cube i want. the problem is if i apply transformation now all the cube will transform together. i want to transform them separetly. i don't understand how to use it in windows. could u kindly provide me the code plese. thanks for reply

regards
isoprog
Quote:Original post by Isoprog
the problem is if i apply transformation now all the cube will transform together. i want to transform them separetly.

This sounds like an issue with your rendering process. Could you post the code you have for drawing your cubes?
i tryed much and stucked here. it is picking very strangely. could u kindly figure it out. i m posting the sample framework but the basic is same as i started with the same framework. sorry but i can't post my main source code because it is too much long and contain some extra cpp and h files. the primitive rendering process is same. in main application it creates the cube from menu and here it creates pressing space.

////////////////////////////////////
// //
// Isoprog 2009 //
// A Simple openGL Framework //
// Press Space To Create A Cube //
// //
////////////////////////////////////
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>

#define SELECT 5
#define PLANE 1
#define CONE 2
#define CUBE 3
#define CYLINDER 4

GLsizei width;
GLsizei height;

HDC hDC=NULL;
HGLRC hRC=NULL;
HWND hWnd=NULL;
HINSTANCE hInstance;

int createcube = 0;

bool keys[256];
bool active=TRUE;
bool fullscreen=FALSE;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
{

glViewport(0,0,width,height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();


gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

int InitGL(GLvoid)
{
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
return TRUE;
}

int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

gluLookAt(10.0, 13.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

glInitNames();
glPushName(0);

glTranslatef(0.0f,0.0f,0.0f);
if(createcube)
{
glLoadName(CUBE);
auxSolidCube(5);
}

glPopMatrix();
glFlush();
return TRUE;
}

// Parse the selection buffer to see which planet/moon was selected
void ProcessMsg(GLuint *pSelectBuff)
{
int id,count;
char cMessage[64];

// How many names on the name stack
count = pSelectBuff[0];

// Bottom of the name stack
id = pSelectBuff[3];

switch(id)
{

case PLANE:
MessageBox(NULL,"pPlane.","Birdao",MB_OK | MB_ICONINFORMATION);

break;

case CONE:
MessageBox(NULL,"pCone.","Birdao",MB_OK | MB_ICONINFORMATION);

break;

case CYLINDER:
MessageBox(NULL,"pCylinder.","Birdao",MB_OK | MB_ICONINFORMATION);

break;

case CUBE:
MessageBox(NULL,"pCube.","Birdao",MB_OK | MB_ICONINFORMATION);

break;


// If nothing was clicked we shouldn't be here!
default:
MessageBox(NULL,"Nothing.","Birdao",MB_OK | MB_ICONINFORMATION);
break;
}


// Display the message about planet and moon selection
MessageBox(NULL, cMessage,0,0);

}

// Process the selection, which is triggered by a right mouse
// click at (xPos, yPos).
#define BUFFER_LENGTH 64
void ProcessSelection(int xPos, int yPos)
{
// Space for selection buffer
GLuint selectBuff[BUFFER_LENGTH];

// Hit counter and viewport storeage
GLint hits, viewport[4];

// Setup selection buffer
glSelectBuffer(BUFFER_LENGTH, selectBuff);

// Get the viewport
glGetIntegerv(GL_VIEWPORT, viewport);

// Switch to projection and save the matrix
glMatrixMode(GL_PROJECTION);
glPushMatrix();

// Change render mode
glRenderMode(GL_SELECT);

// Establish new clipping volume to be unit cube around
// mouse cursor point (xPos, yPos) and extending two pixels
// in the vertical and horzontal direction
glLoadIdentity();

// Since OpenGL measures
// window coordinates starting at the bottom of the window, and Windows
// measures starting at the top, we need to account for this by
// subtracting the y coordinate from the height of the window. This has
// the effect of reversing the coordinate system (y starts at top)

gluPickMatrix(xPos, yPos, 2,2, viewport);

// Apply perspective matrix
gluPerspective(45.0f,(GLfloat)width/height,0.5f,100.0f);

// Draw the scene
DrawGLScene();

// Collect the hits
hits = glRenderMode(GL_RENDER);

// If a single hit occured, display the info.
if(hits == 1)
ProcessMsg(selectBuff);

// Restore the projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();

// Go back to modelview for normal rendering
glMatrixMode(GL_MODELVIEW);

}

GLvoid KillGLWindow(GLvoid)
{
if (fullscreen)
{
ChangeDisplaySettings(NULL,0);
ShowCursor(TRUE);
}

if (hRC)
{
if (!wglMakeCurrent(NULL,NULL))
{
MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}

if (!wglDeleteContext(hRC))
{
MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL;
}

if (hDC && !ReleaseDC(hWnd,hDC))
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL;
}

if (hWnd && !DestroyWindow(hWnd))
{
MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL;
}

if (!UnregisterClass("OpenGL",hInstance))
{
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL;
}
}


BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat;
WNDCLASS wc;
DWORD dwExstyle;
DWORD dwstyle;
RECT WindowRect;
WindowRect.left=(long)0;
WindowRect.right=(long)width;
WindowRect.top=(long)0;
WindowRect.bottom=(long)height;

fullscreen=fullscreenflag;

hInstance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "OpenGL";

if (!RegisterClass(&wc))
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

if (fullscreen)
{
DEVMODE dmScreenSettings;
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width;
dmScreenSettings.dmPelsHeight = height;
dmScreenSettings.dmBitsPerPel = bits;
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;


if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{

if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE;
}
else
{

MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE;
}
}
}

if (fullscreen)
{
dwExstyle=WS_EX_APPWINDOW;
dwstyle=WS_POPUP;
ShowCursor(FALSE);
}
else
{
dwExstyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwstyle=WS_OVERLAPPEDWINDOW;
}

AdjustWindowRectEx(&WindowRect, dwstyle, FALSE, dwExstyle);


if (!(hWnd=CreateWindowEx( dwExstyle,
"OpenGL",
title,
dwstyle |
WS_CLIPSIBLINGS |
WS_CLIPCHILDREN,
0, 0,
WindowRect.right-WindowRect.left,
WindowRect.bottom-WindowRect.top,
NULL,
NULL,
hInstance,
NULL)))
{
KillGLWindow();
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

static PIXELFORMATDESCRIPTOR pfd=
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
bits,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};

if (!(hDC=GetDC(hWnd)))
{
KillGLWindow();
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))
{
KillGLWindow();
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

if(!SetPixelFormat(hDC,PixelFormat,&pfd))
{
KillGLWindow();
MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

if (!(hRC=wglCreateContext(hDC)))
{
KillGLWindow();
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

if(!wglMakeCurrent(hDC,hRC))
{
KillGLWindow();
MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

ShowWindow(hWnd,SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
ReSizeGLScene(width, height);

if (!InitGL())
{
KillGLWindow();
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

return TRUE;
}

LRESULT CALLBACK WndProc( HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg)
{

case WM_ACTIVATE:
{
if (!HIWORD(wParam))
{
active=TRUE;
}
else
{
active=FALSE;
}

return 0;
}

case WM_SYSCOMMAND:
{
switch (wParam)
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
return 0;
}
break;
}

case WM_LBUTTONDOWN:
{
int xPos = LOWORD(lParam); // horizontal position of cursor
int yPos = HIWORD(lParam); // vertical position of cursor
// Render in selection mode and d isplay results
ProcessSelection(xPos, yPos);
}

case WM_LBUTTONUP:
{
return 0;
}

case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}

case WM_KEYDOWN:
{
if(VK_SPACE)
{
createcube += 1;
}

keys[wParam] = TRUE;
return 0;
}

case WM_KEYUP:
{
keys[wParam] = FALSE;
return 0;
}

case WM_SIZE:
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));
return 0;
}
}


return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
BOOL done=FALSE;

if (!CreateGLWindow("OpenGl",640,480,16,fullscreen))
{
return 0;
}

while(!done)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message==WM_QUIT)
{
done=TRUE;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{

if (active)
{
DrawGLScene();
SwapBuffers(hDC);
}

}
}


KillGLWindow();
return (msg.wParam);
}
kindly comment where i made mistakes. i am getting same error amd same problem in both applications.

regards
isoprog
I don't see any transformations taking place in your DrawGLScene method. Did you take those out? Re-insert the transformations as you had them before (when it wasn't working correctly), and we'll go from there. Also, all we're concerned with is the DrawGLScene method; the rest can be left out.

[Edited by - Omega147 on September 14, 2009 5:23:52 PM]
i haven't transformed anything yet. as i said before if i apply transformation right now every primitives transformes together. i just tryed to do so. all transformation were done with a dialog box and putting the value on it transformes the cube or else(transformation with mouse is little tricky i think). all transformation will be done with picking using a boolean value. i m thinking like that. if the boolean value is true it will transform the selected cube or otherwise. i want to apply the picking first than i want to apply the transformation method depending upon the picking method. i just tryed to transform the cube with glTranslatef. everything moved together. thats why i need picking in my application. actually i took the selection code from a book called " OpenGL Super Bible". i just tryed to do what was written there. thanks
Quote:Original post by Isoprog
if the boolean value is true it will transform the selected cube or otherwise. i want to apply the picking first than i want to apply the transformation method depending upon the picking method. i just tryed to transform the cube with glTranslatef. everything moved together.

I'm assuming your cubes are rendered in the auxSolidCube() method, correct?

The reason all your cubes are transforming rather than one is probably because you're rendering all of them through the same transformation matrix. There should be a unique transformation for each individual cube, as demonstrated in the following pseudocode:

loop cubes array => index i    push matrix    rotate cube    translate cube    render cube    pop matrixend loop
This allows each cube to be transformed independently of all other cubes since, with the help of the push and pop calls, each cube is transformed by a different matrix. That make sense?
Hi,
it is not like that, i mean what if it will create a second cube with the same spacebar than how will i move them separately. if i can pick the cube one by one than it will be possible to translate the two cube separately using a boolean. i just want the pick process to work. there are some problem with the mouse click. could u kindly fix the problem. translating an object with an attribute editor is easy(i will think about mouse later). but the problem is if there are two objects in the world, it translates every object together. now, if i can pick any one object between those two object than i will be able to move those two objects separately. kindly fix the problem. thaks for reply

This topic is closed to new replies.

Advertisement