PDA

View Full Version : Picking with GL_SELECT



07-09-2002, 12:37 AM
I m trying to use a picking function inside a gl soft but it doesnt seem to work.
When I read the selectBuffer values inside are like 3202222222 and when I use hits = glRenderMode(GL_RENDER) hits is worth -8972500

Bob
07-09-2002, 02:21 AM
Way more information is needed. Post some code for example.

07-09-2002, 11:48 PM
These odd numbers just come from the parameters are not initialized =)
Here is my current code, not operational since I m doing lots of testing.

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include <gl/gl.h>
#include <gl/glu.h>
double Sommetx[100],Sommety[100];
/////////////////////////////////////////////////////////////////////////////
// CProfilType

CProfilType::CProfilType()
{
}

CProfilType::~CProfilType()
{
}


BEGIN_MESSAGE_MAP(CProfilType, CWnd)
//{{AFX_MSG_MAP(CProfilType)
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CProfilType message handlers

void CProfilType::OnPaint()
{
CPaintDC dc(this); // device context for painting

// TODO: Add your message handler code here
HDC hdc = ::GetDC(m_hWnd);
HGLRC hglrc;

if (hglrc = wglCreateContext(hdc))
{
// try to make it the thread's current rendering context
if(wglMakeCurrent(hdc, hglrc))
{
initOpengl();
//glClearColor(0,0,0,0);
//glColor3f(1, 1, 1);


}
glClear(GL_COLOR_BUFFER_BIT);
//On dessine ici

glColor3f(0,0,0);

for(float i = -4.9 ; i<5.1 ; i=i+0.35)
{
glBegin(GL_LINES);
glVertex2f(i,-200);
glVertex2f(i,200);
glEnd();
}
for( i = -4.9 ; i<5.5 ; i=i+0.35)
{
glBegin(GL_LINES);
glVertex2f(200,i);
glVertex2f(-200,i);
glEnd();
}
glPointSize(4);
glBegin(GL_POINTS);
glVertex2f(0,-4.9);
glEnd();
//Description de "Faux Points" à titre d'exemple.
Sommetx[0]=-2;
Sommetx[1]=-2;
Sommetx[2]=-1;
Sommetx[3]=1;
Sommetx[4]=2;
Sommetx[5]=2;

Sommety[0]=0;
Sommety[1]=4;
Sommety[2]=5;
Sommety[3]=5;
Sommety[4]=4;
Sommety[5]=0;

// Ici on convertit les points dans le repère écran
ConvertPoints(Sommetx,Sommety,NombreSommetsProfilT ype);
// Ici est le profil type
glLineWidth(2);
glBegin(GL_LINE_LOOP);
for( int j = 0; j <= NombreSommetsProfilType; j++)
{
glVertex2f(Sommetx[j],Sommety[j]);
}
glEnd();
InverseConvertPoints(Sommetx,Sommety,NombreSommets ProfilType);

for(j=0;j<PointEnCours;j++)
{
glBegin(GL_POINTS);
// glVertex2f(point.x,point.y);
glVertex2f(Point[j][0],Point[j][1]);
glEnd();
}
SwapBuffers(hdc);
wglMakeCurrent(NULL, NULL) ;
::ReleaseDC (m_hWnd, hdc) ;
wglDeleteContext(hglrc);

}
// Do not call CWnd::OnPaint() for painting messages}
}
void CProfilType::initOpengl()
{
gluPerspective(90,1,0.1,100);
// gluPerspective(45,140/400,0.1,100);
gluLookAt(0,0,5,0,0,0,0,1,0);
glClearColor(0.86,0.86,0.75,0);
// glClear(GL_COLOR_BUFFER_BIT);
// glLineWidth(1/10);

}

int CProfilType::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
MySetPixelFormat(::GetDC(m_hWnd));
// TODO: Add your specialized creation code here
PointEnCours=0;

return 0;
}

void CProfilType::ConvertPoints(double x[100], double y[100], int i)
{
for (int j = 0 ; j<=i ; j ++)
{
x[j] = x[j] * 0.7;
y[j] = y[j] * 0.7-4.9;
}
}

void CProfilType::InverseConvertPoints(double x[100], double y[100], int i)
{
for (int j = 0 ; j<=i ; j ++)
{
x[j] = x[j] / 0.7;
y[j] = (y[j]+4.9) / 0.7;
}
}

void CProfilType::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
HDC hdc = ::GetDC(m_hWnd);
HGLRC hglrc;
GLuint selectBuf[512];
glInitNames();
glPushName(0);
if (hglrc = wglCreateContext(hdc))
{
// try to make it the thread's current rendering context
if(wglMakeCurrent(hdc, hglrc))
{
initOpengl();
//glClearColor(0,0,0,0);
//glColor3f(1, 1, 1);


}

// glClear(GL_COLOR_BUFFER_BIT);
glRenderMode(GL_RENDER);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT,viewport);
glSelectBuffer(512, selectBuf);
if(ModeSelection==1)
{
// OnPaint();
//Stocke le point dans un tableau
Point[PointEnCours][0]=point.x;
Point[PointEnCours][1]=point.y;
double c = Point[PointEnCours][0]=(Point[PointEnCours][0]-200)/40;
double d = Point[PointEnCours][1]=(200-Point[PointEnCours][1])/40;
glPointSize(4);
glRenderMode(GL_RENDER);
glRectf(Point[PointEnCours][0],Point[PointEnCours][1],Point[PointEnCours][0]+1,Point[PointEnCours][1]+1);

glBegin(GL_POINTS);
// glVertex2f(point.x,point.y);
glVertex2f(Point[PointEnCours][0],Point[PointEnCours][1]);
glEnd();
glRenderMode(GL_SELECT);

glLoadName(10);
glColor3f(1,0,0);
glRecti(c,d,c+1,d+1);

glBegin(GL_POINTS);
// glVertex2f(point.x,point.y);
glVertex2f(Point[PointEnCours][0],Point[PointEnCours][1]);
glEnd();
PointEnCours++;
// OnPaint();
// this->Invalidate();
}
double a =(GLdouble) point.x/40-5;
double b =(GLdouble) (viewport[3] - point.y)/40-5;
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPickMatrix(a,b ,
5.0,5.0,viewport);
gluPerspective(90,1,0.1,100);

glPopMatrix();
GLuint hits = glRenderMode(GL_RENDER);
if (hits==2) ModeSelection=0;
SwapBuffers(hdc);
wglMakeCurrent(NULL, NULL) ;
::ReleaseDC (m_hWnd, hdc) ;
wglDeleteContext(hglrc);
CWnd::OnLButtonDown(nFlags, point);
}
}
So now here is what I want to do:
In Point mode, a click draws a point. Whenever, if you click upon a point already here, you select it (and change its color).
In the next steps I will draw surfaces but until then I need to know how to select.

Thanx by advance.

Bob
07-10-2002, 02:39 AM
Your selection code seems to be strange.

First you enter selection mode, then you draw your stuff, and THEN you set up the matrices. Wouldn't it make more sense if you set up the matrice BEFORE you draw your objects?

And the way you set up the matrices makes no sense either.



glPushMatrix();
glLoadIdentity();
gluPickMatrix(a,b ,
5.0,5.0,viewport);
gluPerspective(90,1,0.1,100);
glPopMatrix();

First you save the matrix, then you modify it, and then you restore it. In other words, that piece of code will do nothing.

Batti
07-10-2002, 07:53 AM
see nehe.gamedev.net tutorial 32 for very nice help!

07-11-2002, 05:10 AM
Here an updated version which follows carefully NeHe s code. This isn t work either, the name buffer is staying desperately empty.

// ProfilType.cpp : implementation file
//

#include "stdafx.h"
#include "Front.h"
#include "ProfilType.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include <gl/gl.h>
#include <gl/glu.h>
double Sommetx[100],Sommety[100];
/////////////////////////////////////////////////////////////////////////////
// CProfilType

CProfilType::CProfilType()
{
}

CProfilType::~CProfilType()
{
}


BEGIN_MESSAGE_MAP(CProfilType, CWnd)
//{{AFX_MSG_MAP(CProfilType)
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CProfilType message handlers

void CProfilType::OnPaint()
{
CPaintDC dc(this); // device context for painting

// TODO: Add your message handler code here
HDC hdc = ::GetDC(m_hWnd);
HGLRC hglrc;

if (hglrc = wglCreateContext(hdc))
{
// try to make it the thread's current rendering context
if(wglMakeCurrent(hdc, hglrc))
{
initOpengl();
//glClearColor(0,0,0,0);
//glColor3f(1, 1, 1);


}
glClear(GL_COLOR_BUFFER_BIT);
//On dessine ici

glColor3f(0,0,0);

for(float i = -4.9 ; i<5.1 ; i=i+0.35)
{
glBegin(GL_LINES);
glVertex2f(i,-200);
glVertex2f(i,200);
glEnd();
}
for( i = -4.9 ; i<5.5 ; i=i+0.35)
{
glBegin(GL_LINES);
glVertex2f(200,i);
glVertex2f(-200,i);
glEnd();
}
glPointSize(4);
glBegin(GL_POINTS);
glVertex2f(0,-4.9);
glEnd();
//Description de "Faux Points" à titre d'exemple.
Sommetx[0]=-2;
Sommetx[1]=-2;
Sommetx[2]=-1;
Sommetx[3]=1;
Sommetx[4]=2;
Sommetx[5]=2;

Sommety[0]=0;
Sommety[1]=4;
Sommety[2]=5;
Sommety[3]=5;
Sommety[4]=4;
Sommety[5]=0;

// Ici on convertit les points dans le repère écran
ConvertPoints(Sommetx,Sommety,NombreSommetsProfilT ype);
// Ici est le profil type
glLineWidth(2);
glBegin(GL_LINE_LOOP);
for( int j = 0; j <= NombreSommetsProfilType; j++)
{
glVertex2f(Sommetx[j],Sommety[j]);
}
glEnd();
InverseConvertPoints(Sommetx,Sommety,NombreSommets ProfilType);

for(j=0;j<PointEnCours;j++)
{
glBegin(GL_POINTS);
// glVertex2f(point.x,point.y);
glVertex2f(Point[j][0],Point[j][1]);
glEnd();
}

SwapBuffers(hdc);
wglMakeCurrent(NULL, NULL) ;
::ReleaseDC (m_hWnd, hdc) ;
wglDeleteContext(hglrc);

}
// Do not call CWnd::OnPaint() for painting messages}
}
void CProfilType::initOpengl()
{
gluPerspective(90,1,0.1,100);
// gluPerspective(45,140/400,0.1,100);
gluLookAt(0,0,5,0,0,0,0,1,0);
glClearColor(0.86,0.86,0.75,0);
// glClear(GL_COLOR_BUFFER_BIT);
// glLineWidth(1/10);

}

int CProfilType::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
MySetPixelFormat(::GetDC(m_hWnd));
// TODO: Add your specialized creation code here
PointEnCours=0;

return 0;
}

void CProfilType::ConvertPoints(double x[100], double y[100], int i)
{
for (int j = 0 ; j<=i ; j ++)
{
x[j] = x[j] * 0.7;
y[j] = y[j] * 0.7-4.9;
}
}

void CProfilType::InverseConvertPoints(double x[100], double y[100], int i)
{
for (int j = 0 ; j<=i ; j ++)
{
x[j] = x[j] / 0.7;
y[j] = (y[j]+4.9) / 0.7;
}
}

void CProfilType::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
HDC hdc = ::GetDC(m_hWnd);
HGLRC hglrc;


if (hglrc = wglCreateContext(hdc))
{
// try to make it the thread's current rendering context
if(wglMakeCurrent(hdc, hglrc))
{
initOpengl();
//glClearColor(0,0,0,0);
//glColor3f(1, 1, 1);
}
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT,viewport);

double a =(GLdouble) point.x/40-5;
double b =(GLdouble) (viewport[3] - point.y)/40-5;

// glClear(GL_COLOR_BUFFER_BIT);
// glRenderMode(GL_RENDER);


if(ModeSelection==1)
{
// OnPaint();
//Stocke le point dans un tableau
Point[PointEnCours][0]=point.x;
Point[PointEnCours][1]=point.y;
double c = Point[PointEnCours][0]=(Point[PointEnCours][0]-200)/40;
double d = Point[PointEnCours][1]=(200-Point[PointEnCours][1])/40;
glPointSize(4);

glColor3f(0,0,0);
glRenderMode(GL_RENDER);
// glRectf(Point[PointEnCours][0],Point[PointEnCours][1],Point[PointEnCours][0]+1,Point[PointEnCours][1]+1);

glBegin(GL_POINTS);
// glVertex2f(point.x,point.y);
glVertex2f(Point[PointEnCours][0],Point[PointEnCours][1]);
glEnd();
// glLoadName(PointEnCours);
glSelectBuffer(512, selectBuf);
(void) glRenderMode(GL_SELECT);
glInitNames();
glPushName(-1);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// gluPickMatrix(point.x,400-point.y , 4.0,4.0,viewport);
gluPickMatrix(a,b , 4,4,viewport);
gluPerspective(90,1,0.1,100);

glMatrixMode(GL_MODELVIEW);


glColor3f(1,0,0);
for(int i=0;i<=PointEnCours;i++)
{
glPushName(i);
glBegin(GL_POINTS);
// glVertex2f(point.x,point.y);
glVertex2f(Point[i][0],Point[i][1]);
glEnd();
glPopName();
}

// glPopName();

PointEnCours++;
// OnPaint();
// this->Invalidate();
}


glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
GLuint hits=0;
hits = glRenderMode(GL_RENDER);

if (hits==2)
{
// glMode(GL_RENDER);
}
SwapBuffers(hdc);
wglMakeCurrent(NULL, NULL) ;
::ReleaseDC (m_hWnd, hdc) ;
wglDeleteContext(hglrc);
CWnd::OnLButtonDown(nFlags, point);
}
}

Jonus
07-12-2002, 01:36 AM
Go here and get that Object Selection (http://www.gametutorials.com/Tutorials/OpenGL/OpenGL_Pg3.htm) .

There is a bug in some of the drivers so you have to write an additional glBegin(GL_POINTS);glEnd();. But i don't konw anymore where to write them http://www.opengl.org/discussion_boards/ubb/smile.gif.

[This message has been edited by Jonus (edited 07-12-2002).]

07-12-2002, 06:04 AM
I ll have to get a glance at this page (not working currently).
I gave up with PickMatrix.
I m now using my own picking method. I draw objects one by one and if then I get the pixel color under the mouse: if it s background color, then I didn t pick an object, if it s another color I picked one.
It works well so far, still a bit of work thou.