Archived

This topic is now archived and is closed to further replies.

picking problem

This topic is 5576 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

hi there, i have been experimenting with picking but can't seem to get it to work on my computer with a 3D Prophet 4500 card. The program seems to work other machines though(Tnt2, Voodoo3) Anyone can check if it works on your system???
    
#include "sphere.h" 
#include <glut.h>
#include <iostream>
#include <cassert>

using namespace std;

Sphere	sphere0;
Sphere	sphere1;
Sphere	sphere2;
GLuint select_buffer[100];
GLfloat angle = 0;

const GLuint RED_SPHERE   = 10;
const GLuint GREEN_SPHERE = 20;
const GLuint BLUE_SPHERE  = 30;

void lights() 
{
	// lights

	GLfloat position[] = { 500.0f, 0.0f, 500.0f, 1.0f };
	GLfloat ambient[]  = { 0.6f, 0.6f, 0.6f, 1.0f };
	GLfloat diffuse[]  = { 1.0f, 1.0f, 1.0f, 1.0f };
	GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
	GLfloat emission[] = { 0.0f, 0.0f, 0.0f, 1.0f };

	glLightfv(GL_LIGHT0, GL_POSITION,	position);
	glLightfv(GL_LIGHT0, GL_AMBIENT,	ambient);
	glLightfv(GL_LIGHT0, GL_DIFFUSE,	diffuse);
	glLightfv(GL_LIGHT0, GL_SPECULAR,	specular);
	glLightfv(GL_LIGHT0, GL_EMISSION,	emission);
}

void displayfunc()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(200.0f, 200.0f,   0.0f, 
			    0.0f,   0.0f,   0.0f, 
				0.0f,   0.0f,   1.0f);

	lights();

	glRotatef(angle, 0.0f, 0.0f, 1.0f);
	
	sphere0.draw();
	sphere1.draw();
	sphere2.draw();

	angle += 0.5f;
	if(angle > 360.0f) {
		angle -= 360.0f;
	}
	glutSwapBuffers();
}

void reshapefunc(int width, int height)
{
	GLfloat aspect = (GLfloat) width / (GLfloat) height;
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, aspect, 0.1f, 1000.0f);
	glViewport(0, 0, width, height);
}

void idlefunc()
{
	glutPostRedisplay();
}

void pick(int x, int y)
{
	GLint viewport[4];
	glGetIntegerv(GL_VIEWPORT, viewport);

	GLfloat width  = viewport[2];
	GLfloat height = viewport[3];
	GLfloat aspect = width / height;

	// opengl windows coordinates is

	// x to the right & y upwards

	// but glut gives mouse coordinates with

	// x to the right & y downwards

	// also, glut give mouse coordinates with respect to 

	// client area but opengl is with respect to viewport

	// do the following conversion :

	GLuint gl_x = x - viewport[0];
	GLuint gl_y = viewport[1] + viewport[3] - y - 1;

	cout << "***************************************" << endl;
	cout << "               PICK                    " << endl;
	cout << "***************************************" << endl;
	cout << "Pick Matrix : gl_x = " << gl_x << " gl_y = " << gl_y << endl;

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();	
	gluPickMatrix(gl_x, gl_y,	// coordinates

				  1, 1,			// size 

				  viewport);
	gluPerspective(45.0f, aspect, 0.1f, 1000.0f);

	// drawing for selection

	glRenderMode(GL_SELECT); // note that glSelectBuffer MUST be called before glRenderMode(GL_SELECT)

	glInitNames(); // gl*Names functions are ignored unless in GL_SELECT render mode

	glPushName(0);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(200.0f, 200.0f,   0.0f, 
				0.0f,   0.0f,   0.0f, 
				0.0f,   0.0f,   1.0f);
	glRotatef(angle, 0.0f, 0.0f, 1.0f);
	glLoadName(RED_SPHERE);
	sphere0.draw();
	glLoadName(GREEN_SPHERE);
	sphere1.draw();	
	glLoadName(BLUE_SPHERE);
	sphere2.draw();	
	glFlush();
	// end drawing for selection


	GLuint hits = glRenderMode(GL_RENDER);

	cout << "number of hits = " << hits << endl;
	
	// structure for a single hit record (all integers)

	//

	// 1. number of names on name stack when hit occured

	// 2. minimum depth of all hit primitives

	// 3. maximum depth of all hit primitives 

	// 4. entries in name stack

	//


	GLuint *p = select_buffer;
	GLuint nearest_obj = 0;
	GLuint most_min_depth = 0;

	cout << "iterate through all hit records" << endl;

	// loop thru' all hit records

	for(GLuint i=0; i<hits; i++) {

		cout << "HIT RECORD " << i << " :" << endl;

		GLuint name_count = *p;

		cout << "hit " << i << endl;
		cout << "number of names on name stack = " << name_count << endl;
		
		GLuint min_depth = *(++p);
		GLuint max_depth = *(++p);

		cout << "min depth = " << min_depth << endl;
		cout << "max depth = " << max_depth << endl;
		for(GLuint j=0; j<name_count; j++) {
			cout << "name " << j << " = " << *(++p) << endl;
		}

		// if this is the first hit to be examined...

		// or this object has the minimum depth

		// then set nearest obj so far to this obj

		if(most_min_depth == 0 || min_depth < most_min_depth) {
			most_min_depth = min_depth;
			nearest_obj = *p;
			cout << "nearest_obj = " << *p << endl;
		}
		p++;
	}

	sphere0.hide_bbox();
	sphere1.hide_bbox();
	sphere2.hide_bbox();

	if(nearest_obj == RED_SPHERE) {
		sphere0.show_bbox();
		cout << "red sphere picked" << endl;
	}
	else if(nearest_obj == GREEN_SPHERE) {
		sphere1.show_bbox();
		cout << "green sphere picked" << endl;
	}
	else if(nearest_obj == BLUE_SPHERE) {
		sphere2.show_bbox();
		cout << "blue sphere picked" << endl;
	}

	// reset the projection matrix

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();		
	gluPerspective(45.0f, aspect, 0.1f, 1000.0f);

	// redraw

	glutPostRedisplay();
}

void mousefunc(int button, int state, int x, int y)
{
	if(state == GLUT_DOWN) {
		pick(x, y);
	}
}

void init()
{
	// gl settings

	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);				
	glClearDepth(1.0f);												
	glDepthFunc(GL_LEQUAL);							
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

	// selection

	glSelectBuffer(100, select_buffer);

	// light

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

	// sphere 0 - RED

	sphere0.toggle_bbox();
	sphere0.material.set_ambient(0.2f, 0.2f, 0.2f, 1.0f);
	sphere0.material.set_diffuse(0.5f, 0.0f, 0.0f, 1.0f);
	sphere0.material.set_specular(0.6f, 0.6f, 0.6f, 1.0f);
	sphere0.material.set_emission(0.0f, 0.0f, 0.0f, 1.0f);
	sphere0.material.set_shininess(40); // 0.0f to 128.0f

	sphere0.set_position(100, 0, 0);
	sphere0.set_radius(20);
	sphere0.set_slices(40);
	sphere0.set_stacks(40);

	// sphere 1 - GREEN

	sphere1.material.set_ambient(0.2f, 0.2f, 0.2f, 1.0f);
	sphere1.material.set_diffuse(0.0f, 0.5f, 0.0f, 1.0f);
	sphere1.material.set_specular(0.6f, 0.6f, 0.6f, 1.0f);
	sphere1.material.set_emission(0.0f, 0.0f, 0.0f, 1.0f);
	sphere1.material.set_shininess(40);
	sphere1.set_position(0, 0, 0);
	sphere1.set_radius(20);
	sphere1.set_slices(40);
	sphere1.set_stacks(40);

	// sphere 2 - BLUE

	sphere2.material.set_ambient(0.2f, 0.2f, 0.2f, 1.0f);
	sphere2.material.set_diffuse(0.0f, 0.0f, 0.5f, 1.0f);
	sphere2.material.set_specular(1.0f, 1.0f, 1.0f, 1.0f);
	sphere2.material.set_emission(0.0f, 0.0f, 0.0f, 1.0f);
	sphere2.material.set_shininess(40);	
	sphere2.set_position(-100, 0, 0);
	sphere2.set_radius(20);
	sphere2.set_slices(40);
	sphere2.set_stacks(40);
}

int main(int argc, char *argv[])
{
	glutInitWindowSize(320, 240);
	glutInitWindowPosition(100, 100);
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH |GLUT_DOUBLE);
	glutCreateWindow("picking - click sphere to select");
	glutDisplayFunc(displayfunc);
	glutReshapeFunc(reshapefunc);
	glutIdleFunc(idlefunc);
	glutMouseFunc(mousefunc);

	init();

	glutMainLoop();
	return 0;
}
  

      
#ifndef SPHERE_H
#define SPHERE_H

#include "material.h"
#include "win32_gl.h"
#include <gl\gl.h>
#include <gl\glu.h>

class Sphere {
public:
	Material material;

	Sphere();
	~Sphere();
	void set_position(float x, float y, float z);
	void set_color(float r, float g, float b);
	void set_radius(float radius);
	void set_slices(GLuint slices);
	void set_stacks(GLuint stacks);
	void toggle_bbox();
	void show_bbox();
	void hide_bbox();
	void draw();
private:	
	GLfloat x;
	GLfloat y;
	GLfloat z;

	GLfloat r;
	GLfloat g;
	GLfloat b;

	GLUquadric *quadric;
	GLfloat radius;
	GLuint slices;
	GLuint stacks;

	bool bbox_visible; 

	void draw_bbox();
};

#endif // include guard

  

      
#include "sphere.h"
#include <cassert>

Sphere::Sphere() : bbox_visible(false) {
	quadric = gluNewQuadric();

	if(!quadric)
		assert(false);
}

Sphere::~Sphere() {
	gluDeleteQuadric(quadric);
}

void Sphere::set_position(float x, float y, float z) {
	Sphere::x = x;
	Sphere::y = y;
	Sphere::z = z;
}

void Sphere::set_color(float r, float g, float b) {
	Sphere::r = r;
	Sphere::g = g;
	Sphere::b = b;
}

void Sphere::set_radius(float radius) {
	Sphere::radius = radius;
}

void Sphere::set_slices(GLuint slices) {
	Sphere::slices = slices;
}

void Sphere::set_stacks(GLuint stacks) {
	Sphere::stacks = stacks;
}

void Sphere::toggle_bbox() {
	bbox_visible = !bbox_visible;
}

void Sphere::show_bbox() {
	bbox_visible = true;
}

void Sphere::hide_bbox() {
	bbox_visible = false;
}

void Sphere::draw() {
	glPushMatrix();
		glTranslatef(x, y, z);
		glMaterialfv(GL_FRONT, GL_AMBIENT,  material.get_ambient());
		glMaterialfv(GL_FRONT, GL_DIFFUSE,  material.get_diffuse());
		glMaterialfv(GL_FRONT, GL_SPECULAR, material.get_specular());
		glMaterialfv(GL_FRONT, GL_EMISSION, material.get_emission());
		glMaterialf(GL_FRONT, GL_SHININESS, material.get_shininess());
		gluSphere(quadric, radius, slices, stacks);
		if(bbox_visible)
			draw_bbox();
	glPopMatrix();
}


void Sphere::draw_bbox() {
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	glDisable(GL_LIGHTING);
	glColor3f(1.0f, 1.0f, 0.0f);
	
	glBegin(GL_QUAD_STRIP);	
		// vertical walls

		// front, right, back, left

		// total five vertical edges to define

		
		// first edge : near-left

		glVertex3f(-radius, -radius, -radius);
		glVertex3f(-radius, -radius,  radius);
		
		// second edge : near-right

		glVertex3f( radius, -radius, -radius);
		glVertex3f( radius, -radius,  radius);
		
		// third edge : far-right

		glVertex3f( radius,  radius, -radius);
		glVertex3f( radius,  radius,  radius);
		
		// fourth edge : far-left

		glVertex3f(-radius,  radius, -radius);
		glVertex3f(-radius,  radius,  radius);
		
		// fifth edge : near-left

		glVertex3f(-radius, -radius, -radius);
		glVertex3f(-radius, -radius,  radius);
	glEnd();
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	glEnable(GL_LIGHTING);
}

  

      
#ifndef MATERIAL_H
#define MATERIAL_H

#include "win32_gl.h"
#include <gl\gl.h>

class Material {
public:
	Material();
	~Material();

	void set_specular(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
	void set_ambient(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
	void set_diffuse(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
	void set_emission(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
	void set_shininess(GLfloat s);
		
	const GLfloat * get_specular() const;
	const GLfloat * get_ambient() const;
	const GLfloat * get_diffuse() const;
	const GLfloat * get_emission() const;
	GLfloat get_shininess() const;
private:
	GLfloat specular[4];
	GLfloat ambient[4];
	GLfloat diffuse[4];
	GLfloat emission[4];
	GLfloat shininess;
};

#endif
  

      
#include "material.h"

Material::Material() {

}

Material::~Material() {

}

void Material::set_ambient(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
	ambient[0] = r;
	ambient[1] = g;
	ambient[2] = b;
	ambient[3] = a;	
}

void Material::set_diffuse(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
	diffuse[0] = r;
	diffuse[1] = g;
	diffuse[2] = b;
	diffuse[3] = a;	
}

void Material::set_specular(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
	specular[0] = r;
	specular[1] = g;
	specular[2] = b;
	specular[3] = a;	
}

void Material::set_emission(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
	emission[0] = r;
	emission[1] = g;
	emission[2] = b;
	emission[3] = a;	
}

void Material::set_shininess(GLfloat s) {
	shininess = s;
}

const GLfloat * Material::get_specular() const {
	return specular;
}

const GLfloat * Material::get_ambient() const {
	return ambient;
}

const GLfloat * Material::get_diffuse() const {
	return diffuse;
}

const GLfloat * Material::get_emission() const {
	return emission;
}

GLfloat Material::get_shininess() const {
	return shininess;
}
  

      
#ifndef WIN32_GL_H
#define WIN32_GL_H

// do the following or else need to include <windows.h> 

// which comes with loads of rubbish


#if defined(_WIN32)
	
	#ifndef WINGDIAPI
		#define WINGDIAPI __declspec(dllimport)
	#endif
	
	#ifndef APIENTRY
		#define APIENTRY __stdcall
	#endif	

	#ifndef CALLBACK
		#define CALLBACK __stdcall
	#endif	

	#ifndef _WCHAR_T_DEFINED
		typedef unsigned short wchar_t;
		#define _WCHAR_T_DEFINED
	#endif

#endif // _WIN32 


#endif // include guard

    
[edited by - mageziyx on September 9, 2002 12:36:05 PM]

Share this post


Link to post
Share on other sites
It works damn well ! good work !

I've tested it on GeForce2MX, GeForce3, GeForce4Ti, Radeon 8500 and G450.

ps: Here's the code in a more copy'n'paste-friendly version :
    
#include <windows.h>


#ifndef WIN32_GL_H
#define WIN32_GL_H
// do the following or else need to include <windows.h>

// which comes with loads of rubbish

#if defined(_WIN32)

#ifndef WINGDIAPI
#define WINGDIAPI __declspec(dllimport)
#endif

#ifndef APIENTRY
#define APIENTRY __stdcall
#endif
#ifndef CALLBACK
#define CALLBACK __stdcall
#endif
#ifndef _WCHAR_T_DEFINED
typedef unsigned short wchar_t;
#define _WCHAR_T_DEFINED
#endif
#endif // _WIN32

#endif // include guard










#ifndef MATERIAL_H
#define MATERIAL_H
#include <gl\gl.h>

class Material {
public:
Material();
~Material();
void set_specular(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
void set_ambient(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
void set_diffuse(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
void set_emission(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
void set_shininess(GLfloat s);

const GLfloat * get_specular() const;
const GLfloat * get_ambient() const;
const GLfloat * get_diffuse() const;
const GLfloat * get_emission() const;
GLfloat get_shininess() const;
private:
GLfloat specular[4];
GLfloat ambient[4];
GLfloat diffuse[4];
GLfloat emission[4];
GLfloat shininess;
};
#endif


Material::Material() {
}
Material::~Material() {
}
void Material::set_ambient(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
ambient[0] = r;
ambient[1] = g;
ambient[2] = b;
ambient[3] = a;
}
void Material::set_diffuse(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
diffuse[0] = r;
diffuse[1] = g;
diffuse[2] = b;
diffuse[3] = a;
}
void Material::set_specular(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
specular[0] = r;
specular[1] = g;
specular[2] = b;
specular[3] = a;
}
void Material::set_emission(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
emission[0] = r;
emission[1] = g;
emission[2] = b;
emission[3] = a;
}
void Material::set_shininess(GLfloat s) {
shininess = s;
}
const GLfloat * Material::get_specular() const {
return specular;
}
const GLfloat * Material::get_ambient() const {
return ambient;
}
const GLfloat * Material::get_diffuse() const {
return diffuse;
}
const GLfloat * Material::get_emission() const {
return emission;
}
GLfloat Material::get_shininess() const {
return shininess;
}










#ifndef SPHERE_H
#define SPHERE_H
#include <gl\glu.h>

class Sphere {
public:
Material material;
Sphere();
~Sphere();
void set_position(float x, float y, float z);
void set_color(float r, float g, float b);
void set_radius(float radius);
void set_slices(GLuint slices);
void set_stacks(GLuint stacks);
void toggle_bbox();
void show_bbox();
void hide_bbox();
void draw();
private:
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat r;
GLfloat g;
GLfloat b;
GLUquadric *quadric;
GLfloat radius;
GLuint slices;
GLuint stacks;
bool bbox_visible;
void draw_bbox();
};
#endif // include guard



#include <cassert>
Sphere::Sphere() : bbox_visible(false) {
quadric = gluNewQuadric();
if(!quadric)
assert(false);
}
Sphere::~Sphere() {
gluDeleteQuadric(quadric);
}
void Sphere::set_position(float x, float y, float z) {
Sphere::x = x;
Sphere::y = y;
Sphere::z = z;
}
void Sphere::set_color(float r, float g, float b) {
Sphere::r = r;
Sphere::g = g;
Sphere::b = b;
}
void Sphere::set_radius(float radius) {
Sphere::radius = radius;
}
void Sphere::set_slices(GLuint slices) {
Sphere::slices = slices;
}
void Sphere::set_stacks(GLuint stacks) {
Sphere::stacks = stacks;
}
void Sphere::toggle_bbox() {
bbox_visible = !bbox_visible;
}
void Sphere::show_bbox() {
bbox_visible = true;
}
void Sphere::hide_bbox() {
bbox_visible = false;
}
void Sphere::draw() {
glPushMatrix();
glTranslatef(x, y, z);
glMaterialfv(GL_FRONT, GL_AMBIENT, material.get_ambient());
glMaterialfv(GL_FRONT, GL_DIFFUSE, material.get_diffuse());
glMaterialfv(GL_FRONT, GL_SPECULAR, material.get_specular());
glMaterialfv(GL_FRONT, GL_EMISSION, material.get_emission());
glMaterialf(GL_FRONT, GL_SHININESS, material.get_shininess());
gluSphere(quadric, radius, slices, stacks);
if(bbox_visible)
draw_bbox();
glPopMatrix();
}
void Sphere::draw_bbox() {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_LIGHTING);
glColor3f(1.0f, 1.0f, 0.0f);

glBegin(GL_QUAD_STRIP);
// vertical walls

// front, right, back, left

// total five vertical edges to define


// first edge : near-left

glVertex3f(-radius, -radius, -radius);
glVertex3f(-radius, -radius, radius);

// second edge : near-right

glVertex3f( radius, -radius, -radius);
glVertex3f( radius, -radius, radius);

// third edge : far-right

glVertex3f( radius, radius, -radius);
glVertex3f( radius, radius, radius);

// fourth edge : far-left

glVertex3f(-radius, radius, -radius);
glVertex3f(-radius, radius, radius);

// fifth edge : near-left

glVertex3f(-radius, -radius, -radius);
glVertex3f(-radius, -radius, radius);
glEnd();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_LIGHTING);
}















#include <glut.h>

#include <iostream>

using namespace std;
Sphere sphere0;
Sphere sphere1;
Sphere sphere2;
GLuint select_buffer[100];
GLfloat angle = 0;
const GLuint RED_SPHERE = 10;
const GLuint GREEN_SPHERE = 20;
const GLuint BLUE_SPHERE = 30;
void lights()
{
// lights

GLfloat position[] = { 500.0f, 0.0f, 500.0f, 1.0f };
GLfloat ambient[] = { 0.6f, 0.6f, 0.6f, 1.0f };
GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat emission[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_POSITION, position);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glLightfv(GL_LIGHT0, GL_EMISSION, emission);
}
void displayfunc()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(200.0f, 200.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f);
lights();
glRotatef(angle, 0.0f, 0.0f, 1.0f);

sphere0.draw();
sphere1.draw();
sphere2.draw();
angle += 0.5f;
if(angle > 360.0f) {
angle -= 360.0f;
}
glutSwapBuffers();
}
void reshapefunc(int width, int height)
{
GLfloat aspect = (GLfloat) width / (GLfloat) height;

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, aspect, 0.1f, 1000.0f);
glViewport(0, 0, width, height);
}
void idlefunc()
{
glutPostRedisplay();
}
void pick(int x, int y)
{
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
GLfloat width = viewport[2];
GLfloat height = viewport[3];
GLfloat aspect = width / height;
// opengl windows coordinates is

// x to the right & y upwards

// but glut gives mouse coordinates with

// x to the right & y downwards

// also, glut give mouse coordinates with respect to

// client area but opengl is with respect to viewport

// do the following conversion :

GLuint gl_x = x - viewport[0];
GLuint gl_y = viewport[1] + viewport[3] - y - 1;
cout << "***************************************" << endl;
cout << " PICK " << endl;
cout << "***************************************" << endl;
cout << "Pick Matrix : gl_x = " << gl_x << " gl_y = " << gl_y << endl;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPickMatrix(gl_x, gl_y, // coordinates

1, 1, // size

viewport);
gluPerspective(45.0f, aspect, 0.1f, 1000.0f);
// drawing for selection

glRenderMode(GL_SELECT); // note that glSelectBuffer MUST be called before glRenderMode(GL_SELECT)

glInitNames(); // gl*Names functions are ignored unless in GL_SELECT render mode

glPushName(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(200.0f, 200.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glLoadName(RED_SPHERE);
sphere0.draw();
glLoadName(GREEN_SPHERE);
sphere1.draw();
glLoadName(BLUE_SPHERE);
sphere2.draw();
glFlush();
// end drawing for selection

GLuint hits = glRenderMode(GL_RENDER);
cout << "number of hits = " << hits << endl;

// structure for a single hit record (all integers)

//

// 1. number of names on name stack when hit occured

// 2. minimum depth of all hit primitives

// 3. maximum depth of all hit primitives

// 4. entries in name stack

//

GLuint *p = select_buffer;
GLuint nearest_obj = 0;
GLuint most_min_depth = 0;
cout << "iterate through all hit records" << endl;
// loop thru' all hit records

for(GLuint i=0; i<hits; i++) {
cout << "HIT RECORD " << i << " :" << endl;
GLuint name_count = *p;
cout << "hit " << i << endl;
cout << "number of names on name stack = " << name_count << endl;

GLuint min_depth = *(++p);
GLuint max_depth = *(++p);
cout << "min depth = " << min_depth << endl;
cout << "max depth = " << max_depth << endl;
for(GLuint j=0; j<name_count; j++) {
cout << "name " << j << " = " << *(++p) << endl;
}
// if this is the first hit to be examined...

// or this object has the minimum depth

// then set nearest obj so far to this obj

if(most_min_depth == 0 || min_depth < most_min_depth) {
most_min_depth = min_depth;
nearest_obj = *p;
cout << "nearest_obj = " << *p << endl;
}
p++;
}
sphere0.hide_bbox();
sphere1.hide_bbox();
sphere2.hide_bbox();
if(nearest_obj == RED_SPHERE) {
sphere0.show_bbox();
cout << "red sphere picked" << endl;
}
else if(nearest_obj == GREEN_SPHERE) {
sphere1.show_bbox();
cout << "green sphere picked" << endl;
}
else if(nearest_obj == BLUE_SPHERE) {
sphere2.show_bbox();
cout << "blue sphere picked" << endl;
}
// reset the projection matrix

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, aspect, 0.1f, 1000.0f);
// redraw

glutPostRedisplay();
}
void mousefunc(int button, int state, int x, int y)
{
if(state == GLUT_DOWN) {
pick(x, y);
}
}
void init()
{
// gl settings

glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
// selection

glSelectBuffer(100, select_buffer);
// light

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
// sphere 0 - RED

sphere0.toggle_bbox();
sphere0.material.set_ambient(0.2f, 0.2f, 0.2f, 1.0f);
sphere0.material.set_diffuse(0.5f, 0.0f, 0.0f, 1.0f);
sphere0.material.set_specular(0.6f, 0.6f, 0.6f, 1.0f);
sphere0.material.set_emission(0.0f, 0.0f, 0.0f, 1.0f);
sphere0.material.set_shininess(40); // 0.0f to 128.0f

sphere0.set_position(100, 0, 0);
sphere0.set_radius(20);
sphere0.set_slices(40);
sphere0.set_stacks(40);
// sphere 1 - GREEN

sphere1.material.set_ambient(0.2f, 0.2f, 0.2f, 1.0f);
sphere1.material.set_diffuse(0.0f, 0.5f, 0.0f, 1.0f);
sphere1.material.set_specular(0.6f, 0.6f, 0.6f, 1.0f);
sphere1.material.set_emission(0.0f, 0.0f, 0.0f, 1.0f);
sphere1.material.set_shininess(40);
sphere1.set_position(0, 0, 0);
sphere1.set_radius(20);
sphere1.set_slices(40);
sphere1.set_stacks(40);
// sphere 2 - BLUE

sphere2.material.set_ambient(0.2f, 0.2f, 0.2f, 1.0f);
sphere2.material.set_diffuse(0.0f, 0.0f, 0.5f, 1.0f);
sphere2.material.set_specular(1.0f, 1.0f, 1.0f, 1.0f);
sphere2.material.set_emission(0.0f, 0.0f, 0.0f, 1.0f);
sphere2.material.set_shininess(40);
sphere2.set_position(-100, 0, 0);
sphere2.set_radius(20);
sphere2.set_slices(40);
sphere2.set_stacks(40);
}
int main(int argc, char *argv[])
{
glutInitWindowSize(320, 240);
glutInitWindowPosition(100, 100);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH |GLUT_DOUBLE);
glutCreateWindow("picking - click sphere to select");
glutDisplayFunc(displayfunc);
glutReshapeFunc(reshapefunc);
glutIdleFunc(idlefunc);
glutMouseFunc(mousefunc);
init();
glutMainLoop();
return 0;
}


[edited by - vincoof on September 9, 2002 2:52:34 PM]

Share this post


Link to post
Share on other sites