另外在设置了拾取矩阵,即gluPickMatrix之后的投影设置有什么要注意的地方吗?
16 个解决方案
#1
我也不懂,帮你顶一下!
#2
呵呵。算错了呗。
在这个论坛里面搜索:碰撞检测 拾取这样的字样,你可以找到很多答案
在这个论坛里面搜索:碰撞检测 拾取这样的字样,你可以找到很多答案
#3
算错了?什么意思啊,我怎么改都不行,头都大了,拜托,帮帮忙啊
#4
不会的,贴出代码。
#5
主要代码如下:
else if((!Shift.Contains(ssAlt))&&(!BSpline_SBtn->Down))//处于选择模式
{
GLuint selectBuf[SELECT_BUFSIZE];
GLint hits;
GLint viewport[4];
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (SELECT_BUFSIZE, selectBuf);
glRenderMode(GL_SELECT);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
// 在鼠标位置生成5X5像素区域
gluPickMatrix ((GLdouble)X,(GLdouble)(viewport[3]-(GLint)Y),5.0f, 5.0f,viewport);
//gluPickMatrix ((GLdouble)X,(GLdouble)(viewport[1]+viewport[3]-(GLint)Y),5.0f, 5.0f,viewport);
gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 1.0, 3001.0);
//glOrtho(-3, 3, -3, 3, 1.0,3001);//正交投影出现错误。。。。。。。。。。。。。。。。
glMatrixMode(GL_MODELVIEW);
RenderScene(GL_SELECT);
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glFlush();
hits = glRenderMode (GL_RENDER);
if(hits){processHits (hits, selectBuf);}
}
另外在RenderScene中:
else if((!Shift.Contains(ssAlt))&&(!BSpline_SBtn->Down))//处于选择模式
{
GLuint selectBuf[SELECT_BUFSIZE];
GLint hits;
GLint viewport[4];
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (SELECT_BUFSIZE, selectBuf);
glRenderMode(GL_SELECT);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
// 在鼠标位置生成5X5像素区域
gluPickMatrix ((GLdouble)X,(GLdouble)(viewport[3]-(GLint)Y),5.0f, 5.0f,viewport);
//gluPickMatrix ((GLdouble)X,(GLdouble)(viewport[1]+viewport[3]-(GLint)Y),5.0f, 5.0f,viewport);
gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 1.0, 3001.0);
//glOrtho(-3, 3, -3, 3, 1.0,3001);//正交投影出现错误。。。。。。。。。。。。。。。。
glMatrixMode(GL_MODELVIEW);
RenderScene(GL_SELECT);
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glFlush();
hits = glRenderMode (GL_RENDER);
if(hits){processHits (hits, selectBuf);}
}
另外在RenderScene中:
#6
glInitNames();
glPushName(0);
glPushMatrix();
glTranslatef(-20.0f,0.0f,0.0f);//在此处加了平移之后也会出现选不中的情况
glLoadName(1);
auxWireSphere(10.0f);
glPopMatrix();
glPushMatrix();
glTranslatef(20.0f,0.0f,0.0f);//在此处加了平移之后也会出现选不中的情况
glLoadName(2);
//glPushName(2);
auxWireSphere(5.0f);
//glPopName();
glPopMatrix();
以前随便点哪里都能选中的问题,原因是少了:glMatrixMode(GL_MODELVIEW);但是现在我将球体平移一个位置后怎么又选不中了呀???????
glPushName(0);
glPushMatrix();
glTranslatef(-20.0f,0.0f,0.0f);//在此处加了平移之后也会出现选不中的情况
glLoadName(1);
auxWireSphere(10.0f);
glPopMatrix();
glPushMatrix();
glTranslatef(20.0f,0.0f,0.0f);//在此处加了平移之后也会出现选不中的情况
glLoadName(2);
//glPushName(2);
auxWireSphere(5.0f);
//glPopName();
glPopMatrix();
以前随便点哪里都能选中的问题,原因是少了:glMatrixMode(GL_MODELVIEW);但是现在我将球体平移一个位置后怎么又选不中了呀???????
#7
《超级宝典》上有好几个拾取的例子,仔细看看。
#8
我看过好几个例子了,不过不是《超级宝典》上的(我没这本书),我的程序和那几个例子也差不多,我实在不知道问题出在什么地方
#9
// Planets.c
// OpenGL SuperBible, Chapter 14
// Demonstrates OpenGL Selection/Picking
// Program by Richard S. Wright Jr.
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <math.h>
#define glRGB(x, y, z) glColor3ub((GLubyte)x, (GLubyte)y, (GLubyte)z)
#define SUN 1
#define MERCURY 2
#define VENUS 3
#define EARTH 4
#define MARS 5
GLfloat fAspect;
// Lighting values
GLfloat whiteLight[] = { 0.35f, 0.35f, 0.35f, 1.0f };
GLfloat sourceLight[] = { 0.65f, 0.65f, 0.65f, 1.0f };
GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Save the matrix state and do the rotations
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Translate the whole scene out and into view
glTranslatef(0.0f, 0.0f, -300.0f);
// Initialize the names stack
glInitNames();
glPushName(0);
// Set material color, Yellow
// Sun
glRGB(255, 255, 0);
glLoadName(SUN);
glutSolidSphere(15.0f, 15, 15);
// Draw Mercury
glRGB(128,0,0);
glPushMatrix();
glTranslatef(24.0f, 0.0f, 0.0f);
glLoadName(MERCURY);
glutSolidSphere(2.0f,15,15);
glPopMatrix();
// Draw Venus
glPushMatrix();
glRGB(128,128,255);
glTranslatef(60.0f, 0.0f, 0.0f);
glLoadName(VENUS);
glutSolidSphere(4.0f,15,15);
glPopMatrix();
// Draw the Earth
glPushMatrix();
glRGB(0,0,255);
glTranslatef(100.0f,0.0f,0.0f);
glLoadName(EARTH);
glutSolidSphere(8.0f,15,15);
glPopMatrix();
// Draw Mars
glRGB(255,0,0);
glPushMatrix();
glTranslatef(150.0f, 0.0f, 0.0f);
glLoadName(MARS);
glutSolidSphere(4.0f,15,15);
glPopMatrix();
// Restore the matrix state
glPopMatrix(); // Modelview matrix
glutSwapBuffers();
}
// Present the information on which planet/sun was selected and displayed
void ProcessPlanet(GLuint id)
{
switch(id)
{
case SUN:
MessageBox(NULL,"You clicked on the Sun!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case MERCURY:
MessageBox(NULL,"You clicked on Mercury!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case VENUS:
MessageBox(NULL,"You clicked on Venus!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case EARTH:
MessageBox(NULL,"You clicked on Earth!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case MARS:
MessageBox(NULL,"You clicked on Mars!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
default:
MessageBox(NULL,"Nothing was clicked on!","Error",MB_OK | MB_ICONEXCLAMATION);
break;
}
}
// 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();
gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport);
// Apply perspective matrix
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Draw the scene
RenderScene();
// Collect the hits
hits = glRenderMode(GL_RENDER);
// If a single hit occured, display the info.
if(hits == 1)
ProcessPlanet(selectBuff[3]);
// Restore the projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// Go back to modelview for normal rendering
glMatrixMode(GL_MODELVIEW);
}
// Process the mouse click
void MouseCallback(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
ProcessSelection(x, y);
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Light values and coordinates
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
glEnable(GL_CULL_FACE); // Do not calculate insides
// Enable lighting
glEnable(GL_LIGHTING);
// Setup and enable light 0
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);
// Enable color tracking
glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// Black blue background
glClearColor(0.60f, 0.60f, 0.60f, 1.0f );
}
void ChangeSize(int w, int h)
{
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Calculate aspect ratio of the window
fAspect = (GLfloat)w/(GLfloat)h;
// Set the perspective coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Field of view of 45 degrees, near and far planes 1.0 and 425
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Modelview matrix reset
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600,300);
glutCreateWindow("Pick a Planet");
glutReshapeFunc(ChangeSize);
glutMouseFunc(MouseCallback);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();
return 0;
}
// OpenGL SuperBible, Chapter 14
// Demonstrates OpenGL Selection/Picking
// Program by Richard S. Wright Jr.
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <math.h>
#define glRGB(x, y, z) glColor3ub((GLubyte)x, (GLubyte)y, (GLubyte)z)
#define SUN 1
#define MERCURY 2
#define VENUS 3
#define EARTH 4
#define MARS 5
GLfloat fAspect;
// Lighting values
GLfloat whiteLight[] = { 0.35f, 0.35f, 0.35f, 1.0f };
GLfloat sourceLight[] = { 0.65f, 0.65f, 0.65f, 1.0f };
GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Save the matrix state and do the rotations
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Translate the whole scene out and into view
glTranslatef(0.0f, 0.0f, -300.0f);
// Initialize the names stack
glInitNames();
glPushName(0);
// Set material color, Yellow
// Sun
glRGB(255, 255, 0);
glLoadName(SUN);
glutSolidSphere(15.0f, 15, 15);
// Draw Mercury
glRGB(128,0,0);
glPushMatrix();
glTranslatef(24.0f, 0.0f, 0.0f);
glLoadName(MERCURY);
glutSolidSphere(2.0f,15,15);
glPopMatrix();
// Draw Venus
glPushMatrix();
glRGB(128,128,255);
glTranslatef(60.0f, 0.0f, 0.0f);
glLoadName(VENUS);
glutSolidSphere(4.0f,15,15);
glPopMatrix();
// Draw the Earth
glPushMatrix();
glRGB(0,0,255);
glTranslatef(100.0f,0.0f,0.0f);
glLoadName(EARTH);
glutSolidSphere(8.0f,15,15);
glPopMatrix();
// Draw Mars
glRGB(255,0,0);
glPushMatrix();
glTranslatef(150.0f, 0.0f, 0.0f);
glLoadName(MARS);
glutSolidSphere(4.0f,15,15);
glPopMatrix();
// Restore the matrix state
glPopMatrix(); // Modelview matrix
glutSwapBuffers();
}
// Present the information on which planet/sun was selected and displayed
void ProcessPlanet(GLuint id)
{
switch(id)
{
case SUN:
MessageBox(NULL,"You clicked on the Sun!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case MERCURY:
MessageBox(NULL,"You clicked on Mercury!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case VENUS:
MessageBox(NULL,"You clicked on Venus!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case EARTH:
MessageBox(NULL,"You clicked on Earth!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case MARS:
MessageBox(NULL,"You clicked on Mars!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
default:
MessageBox(NULL,"Nothing was clicked on!","Error",MB_OK | MB_ICONEXCLAMATION);
break;
}
}
// 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();
gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport);
// Apply perspective matrix
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Draw the scene
RenderScene();
// Collect the hits
hits = glRenderMode(GL_RENDER);
// If a single hit occured, display the info.
if(hits == 1)
ProcessPlanet(selectBuff[3]);
// Restore the projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// Go back to modelview for normal rendering
glMatrixMode(GL_MODELVIEW);
}
// Process the mouse click
void MouseCallback(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
ProcessSelection(x, y);
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Light values and coordinates
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
glEnable(GL_CULL_FACE); // Do not calculate insides
// Enable lighting
glEnable(GL_LIGHTING);
// Setup and enable light 0
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);
// Enable color tracking
glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// Black blue background
glClearColor(0.60f, 0.60f, 0.60f, 1.0f );
}
void ChangeSize(int w, int h)
{
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Calculate aspect ratio of the window
fAspect = (GLfloat)w/(GLfloat)h;
// Set the perspective coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Field of view of 45 degrees, near and far planes 1.0 and 425
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Modelview matrix reset
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600,300);
glutCreateWindow("Pick a Planet");
glutReshapeFunc(ChangeSize);
glutMouseFunc(MouseCallback);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();
return 0;
}
#10
// Moons.c
// OpenGL SuperBible, Chapter 14
// Demonstrates OpenGL Hierarchical Selection/Picking
// Program by Richard S. Wright Jr.
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <math.h>
#define glRGB(x, y, z) glColor3ub((GLubyte)x, (GLubyte)y, (GLubyte)z)
#define EARTH 1
#define MARS 2
#define MOON1 3
#define MOON2 4
GLfloat fAspect;
// Lighting values
GLfloat whiteLight[] = { 0.35f, 0.35f, 0.35f, 1.0f };
GLfloat sourceLight[] = { 0.65f, 0.65f, 0.65f, 1.0f };
GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Save the matrix state and do the rotations
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Translate the whole scene out and into view
glTranslatef(0.0f, 0.0f, -300.0f);
// Initialize the names stack
glInitNames();
glPushName(0);
// Draw the Earth
glPushMatrix();
glRGB(0,0,255);
glTranslatef(-100.0f,0.0f,0.0f);
glLoadName(EARTH);
glutSolidSphere(30.0f, 15, 15);
// Draw the Moon
glTranslatef(45.0f, 0.0f, 0.0f);
glRGB(220,220,220);
glPushName(MOON1);
glutSolidSphere(5.0f, 15, 15);glPopName();
glPopMatrix();
// Draw Mars
glRGB(255,0,0);
glPushMatrix();
glTranslatef(100.0f, 0.0f, 0.0f);
glLoadName(MARS);
glutSolidSphere(20.0f, 15, 15);
// Draw Moon1
glTranslatef(-40.0f, 40.0f, 0.0f);
glRGB(220,220,220);
glPushName(MOON1);
glutSolidSphere(5.0f, 15, 15);
glPopName();
// Draw Moon2
glTranslatef(0.0f, -80.0f, 0.0f);
glPushName(MOON2);
glutSolidSphere(5.0f, 15, 15); glPopName();
glPopMatrix();
// Restore the matrix state
glPopMatrix(); // Modelview matrix
glutSwapBuffers();
}
// Parse the selection buffer to see which planet/moon was selected
void ProcessPlanet(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];
// Select on earth or mars, whichever was picked
switch(id)
{
case EARTH:
strcpy(cMessage,"You clicked Earth.");
// If there is another name on the name stack,
// then it must be the moon that was selected
// This is what was actually clicked on
if(count == 2)
strcat(cMessage,"\nSpecifically the moon.");
break;
case MARS:
strcpy(cMessage,"You clicked Mars.");
// We know the name stack is only two deep. The precise
// moon that was selected will be here.
if(count == 2)
{
if(pSelectBuff[4] == MOON1)
strcat(cMessage,"\nSpecifically Moon #1.");
else
strcat(cMessage,"\nSpecifically Moon #2.");
}
break;
// If nothing was clicked we shouldn't be here!
default:
strcpy(cMessage,"Error - Nothing was clicked on!");
break;
}
// Display the message about planet and moon selection
MessageBox(NULL,cMessage,"Selection Message",MB_OK);
}
// 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. Remember OpenGL specifies the
// y coordinate from the bottom, Windows from the top. So windows position
// (as measured from the top) subtract the height and you get it in terms
// OpenGL Likes.
glLoadIdentity();
gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport);
// Apply perspective matrix
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Draw the scene
RenderScene();
// Collect the hits
hits = glRenderMode(GL_RENDER);
// If a single hit occured, display the info.
if(hits == 1)
ProcessPlanet(selectBuff);
// Restore the projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// Go back to modelview for normal rendering
glMatrixMode(GL_MODELVIEW);
}
// Process the mouse click
void MouseCallback(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
ProcessSelection(x, y);
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Light values and coordinates
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
glEnable(GL_CULL_FACE); // Do not calculate insides
// Enable lighting
glEnable(GL_LIGHTING);
// Setup and enable light 0
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);
// Enable color tracking
glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// Black blue background
glClearColor(0.60f, 0.60f, 0.60f, 1.0f );
}
void ChangeSize(int w, int h)
{
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Calculate aspect ratio of the window
fAspect = (GLfloat)w/(GLfloat)h;
// Set the perspective coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Field of view of 45 degrees, near and far planes 1.0 and 425
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Modelview matrix reset
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600,300);
glutCreateWindow("Pick a Planet or Moon");
glutReshapeFunc(ChangeSize);
glutMouseFunc(MouseCallback);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();
return 0;
}
// OpenGL SuperBible, Chapter 14
// Demonstrates OpenGL Hierarchical Selection/Picking
// Program by Richard S. Wright Jr.
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <math.h>
#define glRGB(x, y, z) glColor3ub((GLubyte)x, (GLubyte)y, (GLubyte)z)
#define EARTH 1
#define MARS 2
#define MOON1 3
#define MOON2 4
GLfloat fAspect;
// Lighting values
GLfloat whiteLight[] = { 0.35f, 0.35f, 0.35f, 1.0f };
GLfloat sourceLight[] = { 0.65f, 0.65f, 0.65f, 1.0f };
GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Save the matrix state and do the rotations
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Translate the whole scene out and into view
glTranslatef(0.0f, 0.0f, -300.0f);
// Initialize the names stack
glInitNames();
glPushName(0);
// Draw the Earth
glPushMatrix();
glRGB(0,0,255);
glTranslatef(-100.0f,0.0f,0.0f);
glLoadName(EARTH);
glutSolidSphere(30.0f, 15, 15);
// Draw the Moon
glTranslatef(45.0f, 0.0f, 0.0f);
glRGB(220,220,220);
glPushName(MOON1);
glutSolidSphere(5.0f, 15, 15);glPopName();
glPopMatrix();
// Draw Mars
glRGB(255,0,0);
glPushMatrix();
glTranslatef(100.0f, 0.0f, 0.0f);
glLoadName(MARS);
glutSolidSphere(20.0f, 15, 15);
// Draw Moon1
glTranslatef(-40.0f, 40.0f, 0.0f);
glRGB(220,220,220);
glPushName(MOON1);
glutSolidSphere(5.0f, 15, 15);
glPopName();
// Draw Moon2
glTranslatef(0.0f, -80.0f, 0.0f);
glPushName(MOON2);
glutSolidSphere(5.0f, 15, 15); glPopName();
glPopMatrix();
// Restore the matrix state
glPopMatrix(); // Modelview matrix
glutSwapBuffers();
}
// Parse the selection buffer to see which planet/moon was selected
void ProcessPlanet(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];
// Select on earth or mars, whichever was picked
switch(id)
{
case EARTH:
strcpy(cMessage,"You clicked Earth.");
// If there is another name on the name stack,
// then it must be the moon that was selected
// This is what was actually clicked on
if(count == 2)
strcat(cMessage,"\nSpecifically the moon.");
break;
case MARS:
strcpy(cMessage,"You clicked Mars.");
// We know the name stack is only two deep. The precise
// moon that was selected will be here.
if(count == 2)
{
if(pSelectBuff[4] == MOON1)
strcat(cMessage,"\nSpecifically Moon #1.");
else
strcat(cMessage,"\nSpecifically Moon #2.");
}
break;
// If nothing was clicked we shouldn't be here!
default:
strcpy(cMessage,"Error - Nothing was clicked on!");
break;
}
// Display the message about planet and moon selection
MessageBox(NULL,cMessage,"Selection Message",MB_OK);
}
// 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. Remember OpenGL specifies the
// y coordinate from the bottom, Windows from the top. So windows position
// (as measured from the top) subtract the height and you get it in terms
// OpenGL Likes.
glLoadIdentity();
gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport);
// Apply perspective matrix
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Draw the scene
RenderScene();
// Collect the hits
hits = glRenderMode(GL_RENDER);
// If a single hit occured, display the info.
if(hits == 1)
ProcessPlanet(selectBuff);
// Restore the projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// Go back to modelview for normal rendering
glMatrixMode(GL_MODELVIEW);
}
// Process the mouse click
void MouseCallback(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
ProcessSelection(x, y);
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Light values and coordinates
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
glEnable(GL_CULL_FACE); // Do not calculate insides
// Enable lighting
glEnable(GL_LIGHTING);
// Setup and enable light 0
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);
// Enable color tracking
glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// Black blue background
glClearColor(0.60f, 0.60f, 0.60f, 1.0f );
}
void ChangeSize(int w, int h)
{
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Calculate aspect ratio of the window
fAspect = (GLfloat)w/(GLfloat)h;
// Set the perspective coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Field of view of 45 degrees, near and far planes 1.0 and 425
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Modelview matrix reset
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600,300);
glutCreateWindow("Pick a Planet or Moon");
glutReshapeFunc(ChangeSize);
glutMouseFunc(MouseCallback);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();
return 0;
}
#11
谢谢!我看过了例子,但是还没找到错误所在,郁闷。。。。。
#12
如果整个场景变换了(平移,缩放,旋转),选择就会出问题,比如物体开始在原点位置,平移之后,还是只能在原先的位置才可以选中,该怎么解决呢?
#13
那不应该,仔细看看投影矩阵和模型矩阵的设置,应该这两个矩阵有问题。
#14
选择部分的代码如下:
{
GLuint selectBuf[SELECT_BUFSIZE];
GLint hits;
GLint viewport[4];
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (SELECT_BUFSIZE, selectBuf);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
(void)glRenderMode(GL_SELECT);
//glInitNames();
//glPushName(0);
glLoadIdentity ();
// 在鼠标位置生成3X3像素区域
gluPickMatrix ((GLdouble)X,(GLdouble)(viewport[3]-(GLint)Y+StatusBar->Height+ToolBar->Height) ,3.0f, 3.0f,viewport);
//gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 1.0, 3001.0); 错误!!!
GLfloat nRange = 10.0;
if (w <= h)
{ glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);}
else
{ glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange); }
glMatrixMode(GL_MODELVIEW);
RenderScene(GL_SELECT);
glMatrixMode (GL_PROJECTION);
glFlush();
hits = glRenderMode (GL_RENDER);
this->Resize();
if(hits){processHits (hits, selectBuf);}
glPopMatrix ();
}
{
GLuint selectBuf[SELECT_BUFSIZE];
GLint hits;
GLint viewport[4];
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (SELECT_BUFSIZE, selectBuf);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
(void)glRenderMode(GL_SELECT);
//glInitNames();
//glPushName(0);
glLoadIdentity ();
// 在鼠标位置生成3X3像素区域
gluPickMatrix ((GLdouble)X,(GLdouble)(viewport[3]-(GLint)Y+StatusBar->Height+ToolBar->Height) ,3.0f, 3.0f,viewport);
//gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 1.0, 3001.0); 错误!!!
GLfloat nRange = 10.0;
if (w <= h)
{ glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);}
else
{ glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange); }
glMatrixMode(GL_MODELVIEW);
RenderScene(GL_SELECT);
glMatrixMode (GL_PROJECTION);
glFlush();
hits = glRenderMode (GL_RENDER);
this->Resize();
if(hits){processHits (hits, selectBuf);}
glPopMatrix ();
}
#15
以上代码中,在投影的时候如果用gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 1.0, 3001.0);
投影,则什么也选不中。
投影,则什么也选不中。
#16
我终于找到了问题所在了,但不知道该怎么解决。问题出在,在FormResize函数中gluPerspective(45.0f, aspect, 1.0, 3001.0);设置了投影之后,紧接着又用gluLookAt函数设置了视点,如果不设置视点,一切正常,设置了视点之后就会出现问题。这该怎么解决呢????????
#1
我也不懂,帮你顶一下!
#2
呵呵。算错了呗。
在这个论坛里面搜索:碰撞检测 拾取这样的字样,你可以找到很多答案
在这个论坛里面搜索:碰撞检测 拾取这样的字样,你可以找到很多答案
#3
算错了?什么意思啊,我怎么改都不行,头都大了,拜托,帮帮忙啊
#4
不会的,贴出代码。
#5
主要代码如下:
else if((!Shift.Contains(ssAlt))&&(!BSpline_SBtn->Down))//处于选择模式
{
GLuint selectBuf[SELECT_BUFSIZE];
GLint hits;
GLint viewport[4];
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (SELECT_BUFSIZE, selectBuf);
glRenderMode(GL_SELECT);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
// 在鼠标位置生成5X5像素区域
gluPickMatrix ((GLdouble)X,(GLdouble)(viewport[3]-(GLint)Y),5.0f, 5.0f,viewport);
//gluPickMatrix ((GLdouble)X,(GLdouble)(viewport[1]+viewport[3]-(GLint)Y),5.0f, 5.0f,viewport);
gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 1.0, 3001.0);
//glOrtho(-3, 3, -3, 3, 1.0,3001);//正交投影出现错误。。。。。。。。。。。。。。。。
glMatrixMode(GL_MODELVIEW);
RenderScene(GL_SELECT);
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glFlush();
hits = glRenderMode (GL_RENDER);
if(hits){processHits (hits, selectBuf);}
}
另外在RenderScene中:
else if((!Shift.Contains(ssAlt))&&(!BSpline_SBtn->Down))//处于选择模式
{
GLuint selectBuf[SELECT_BUFSIZE];
GLint hits;
GLint viewport[4];
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (SELECT_BUFSIZE, selectBuf);
glRenderMode(GL_SELECT);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
// 在鼠标位置生成5X5像素区域
gluPickMatrix ((GLdouble)X,(GLdouble)(viewport[3]-(GLint)Y),5.0f, 5.0f,viewport);
//gluPickMatrix ((GLdouble)X,(GLdouble)(viewport[1]+viewport[3]-(GLint)Y),5.0f, 5.0f,viewport);
gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 1.0, 3001.0);
//glOrtho(-3, 3, -3, 3, 1.0,3001);//正交投影出现错误。。。。。。。。。。。。。。。。
glMatrixMode(GL_MODELVIEW);
RenderScene(GL_SELECT);
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glFlush();
hits = glRenderMode (GL_RENDER);
if(hits){processHits (hits, selectBuf);}
}
另外在RenderScene中:
#6
glInitNames();
glPushName(0);
glPushMatrix();
glTranslatef(-20.0f,0.0f,0.0f);//在此处加了平移之后也会出现选不中的情况
glLoadName(1);
auxWireSphere(10.0f);
glPopMatrix();
glPushMatrix();
glTranslatef(20.0f,0.0f,0.0f);//在此处加了平移之后也会出现选不中的情况
glLoadName(2);
//glPushName(2);
auxWireSphere(5.0f);
//glPopName();
glPopMatrix();
以前随便点哪里都能选中的问题,原因是少了:glMatrixMode(GL_MODELVIEW);但是现在我将球体平移一个位置后怎么又选不中了呀???????
glPushName(0);
glPushMatrix();
glTranslatef(-20.0f,0.0f,0.0f);//在此处加了平移之后也会出现选不中的情况
glLoadName(1);
auxWireSphere(10.0f);
glPopMatrix();
glPushMatrix();
glTranslatef(20.0f,0.0f,0.0f);//在此处加了平移之后也会出现选不中的情况
glLoadName(2);
//glPushName(2);
auxWireSphere(5.0f);
//glPopName();
glPopMatrix();
以前随便点哪里都能选中的问题,原因是少了:glMatrixMode(GL_MODELVIEW);但是现在我将球体平移一个位置后怎么又选不中了呀???????
#7
《超级宝典》上有好几个拾取的例子,仔细看看。
#8
我看过好几个例子了,不过不是《超级宝典》上的(我没这本书),我的程序和那几个例子也差不多,我实在不知道问题出在什么地方
#9
// Planets.c
// OpenGL SuperBible, Chapter 14
// Demonstrates OpenGL Selection/Picking
// Program by Richard S. Wright Jr.
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <math.h>
#define glRGB(x, y, z) glColor3ub((GLubyte)x, (GLubyte)y, (GLubyte)z)
#define SUN 1
#define MERCURY 2
#define VENUS 3
#define EARTH 4
#define MARS 5
GLfloat fAspect;
// Lighting values
GLfloat whiteLight[] = { 0.35f, 0.35f, 0.35f, 1.0f };
GLfloat sourceLight[] = { 0.65f, 0.65f, 0.65f, 1.0f };
GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Save the matrix state and do the rotations
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Translate the whole scene out and into view
glTranslatef(0.0f, 0.0f, -300.0f);
// Initialize the names stack
glInitNames();
glPushName(0);
// Set material color, Yellow
// Sun
glRGB(255, 255, 0);
glLoadName(SUN);
glutSolidSphere(15.0f, 15, 15);
// Draw Mercury
glRGB(128,0,0);
glPushMatrix();
glTranslatef(24.0f, 0.0f, 0.0f);
glLoadName(MERCURY);
glutSolidSphere(2.0f,15,15);
glPopMatrix();
// Draw Venus
glPushMatrix();
glRGB(128,128,255);
glTranslatef(60.0f, 0.0f, 0.0f);
glLoadName(VENUS);
glutSolidSphere(4.0f,15,15);
glPopMatrix();
// Draw the Earth
glPushMatrix();
glRGB(0,0,255);
glTranslatef(100.0f,0.0f,0.0f);
glLoadName(EARTH);
glutSolidSphere(8.0f,15,15);
glPopMatrix();
// Draw Mars
glRGB(255,0,0);
glPushMatrix();
glTranslatef(150.0f, 0.0f, 0.0f);
glLoadName(MARS);
glutSolidSphere(4.0f,15,15);
glPopMatrix();
// Restore the matrix state
glPopMatrix(); // Modelview matrix
glutSwapBuffers();
}
// Present the information on which planet/sun was selected and displayed
void ProcessPlanet(GLuint id)
{
switch(id)
{
case SUN:
MessageBox(NULL,"You clicked on the Sun!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case MERCURY:
MessageBox(NULL,"You clicked on Mercury!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case VENUS:
MessageBox(NULL,"You clicked on Venus!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case EARTH:
MessageBox(NULL,"You clicked on Earth!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case MARS:
MessageBox(NULL,"You clicked on Mars!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
default:
MessageBox(NULL,"Nothing was clicked on!","Error",MB_OK | MB_ICONEXCLAMATION);
break;
}
}
// 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();
gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport);
// Apply perspective matrix
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Draw the scene
RenderScene();
// Collect the hits
hits = glRenderMode(GL_RENDER);
// If a single hit occured, display the info.
if(hits == 1)
ProcessPlanet(selectBuff[3]);
// Restore the projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// Go back to modelview for normal rendering
glMatrixMode(GL_MODELVIEW);
}
// Process the mouse click
void MouseCallback(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
ProcessSelection(x, y);
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Light values and coordinates
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
glEnable(GL_CULL_FACE); // Do not calculate insides
// Enable lighting
glEnable(GL_LIGHTING);
// Setup and enable light 0
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);
// Enable color tracking
glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// Black blue background
glClearColor(0.60f, 0.60f, 0.60f, 1.0f );
}
void ChangeSize(int w, int h)
{
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Calculate aspect ratio of the window
fAspect = (GLfloat)w/(GLfloat)h;
// Set the perspective coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Field of view of 45 degrees, near and far planes 1.0 and 425
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Modelview matrix reset
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600,300);
glutCreateWindow("Pick a Planet");
glutReshapeFunc(ChangeSize);
glutMouseFunc(MouseCallback);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();
return 0;
}
// OpenGL SuperBible, Chapter 14
// Demonstrates OpenGL Selection/Picking
// Program by Richard S. Wright Jr.
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <math.h>
#define glRGB(x, y, z) glColor3ub((GLubyte)x, (GLubyte)y, (GLubyte)z)
#define SUN 1
#define MERCURY 2
#define VENUS 3
#define EARTH 4
#define MARS 5
GLfloat fAspect;
// Lighting values
GLfloat whiteLight[] = { 0.35f, 0.35f, 0.35f, 1.0f };
GLfloat sourceLight[] = { 0.65f, 0.65f, 0.65f, 1.0f };
GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Save the matrix state and do the rotations
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Translate the whole scene out and into view
glTranslatef(0.0f, 0.0f, -300.0f);
// Initialize the names stack
glInitNames();
glPushName(0);
// Set material color, Yellow
// Sun
glRGB(255, 255, 0);
glLoadName(SUN);
glutSolidSphere(15.0f, 15, 15);
// Draw Mercury
glRGB(128,0,0);
glPushMatrix();
glTranslatef(24.0f, 0.0f, 0.0f);
glLoadName(MERCURY);
glutSolidSphere(2.0f,15,15);
glPopMatrix();
// Draw Venus
glPushMatrix();
glRGB(128,128,255);
glTranslatef(60.0f, 0.0f, 0.0f);
glLoadName(VENUS);
glutSolidSphere(4.0f,15,15);
glPopMatrix();
// Draw the Earth
glPushMatrix();
glRGB(0,0,255);
glTranslatef(100.0f,0.0f,0.0f);
glLoadName(EARTH);
glutSolidSphere(8.0f,15,15);
glPopMatrix();
// Draw Mars
glRGB(255,0,0);
glPushMatrix();
glTranslatef(150.0f, 0.0f, 0.0f);
glLoadName(MARS);
glutSolidSphere(4.0f,15,15);
glPopMatrix();
// Restore the matrix state
glPopMatrix(); // Modelview matrix
glutSwapBuffers();
}
// Present the information on which planet/sun was selected and displayed
void ProcessPlanet(GLuint id)
{
switch(id)
{
case SUN:
MessageBox(NULL,"You clicked on the Sun!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case MERCURY:
MessageBox(NULL,"You clicked on Mercury!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case VENUS:
MessageBox(NULL,"You clicked on Venus!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case EARTH:
MessageBox(NULL,"You clicked on Earth!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
case MARS:
MessageBox(NULL,"You clicked on Mars!","Info",MB_OK | MB_ICONEXCLAMATION);
break;
default:
MessageBox(NULL,"Nothing was clicked on!","Error",MB_OK | MB_ICONEXCLAMATION);
break;
}
}
// 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();
gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport);
// Apply perspective matrix
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Draw the scene
RenderScene();
// Collect the hits
hits = glRenderMode(GL_RENDER);
// If a single hit occured, display the info.
if(hits == 1)
ProcessPlanet(selectBuff[3]);
// Restore the projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// Go back to modelview for normal rendering
glMatrixMode(GL_MODELVIEW);
}
// Process the mouse click
void MouseCallback(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
ProcessSelection(x, y);
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Light values and coordinates
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
glEnable(GL_CULL_FACE); // Do not calculate insides
// Enable lighting
glEnable(GL_LIGHTING);
// Setup and enable light 0
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);
// Enable color tracking
glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// Black blue background
glClearColor(0.60f, 0.60f, 0.60f, 1.0f );
}
void ChangeSize(int w, int h)
{
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Calculate aspect ratio of the window
fAspect = (GLfloat)w/(GLfloat)h;
// Set the perspective coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Field of view of 45 degrees, near and far planes 1.0 and 425
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Modelview matrix reset
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600,300);
glutCreateWindow("Pick a Planet");
glutReshapeFunc(ChangeSize);
glutMouseFunc(MouseCallback);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();
return 0;
}
#10
// Moons.c
// OpenGL SuperBible, Chapter 14
// Demonstrates OpenGL Hierarchical Selection/Picking
// Program by Richard S. Wright Jr.
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <math.h>
#define glRGB(x, y, z) glColor3ub((GLubyte)x, (GLubyte)y, (GLubyte)z)
#define EARTH 1
#define MARS 2
#define MOON1 3
#define MOON2 4
GLfloat fAspect;
// Lighting values
GLfloat whiteLight[] = { 0.35f, 0.35f, 0.35f, 1.0f };
GLfloat sourceLight[] = { 0.65f, 0.65f, 0.65f, 1.0f };
GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Save the matrix state and do the rotations
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Translate the whole scene out and into view
glTranslatef(0.0f, 0.0f, -300.0f);
// Initialize the names stack
glInitNames();
glPushName(0);
// Draw the Earth
glPushMatrix();
glRGB(0,0,255);
glTranslatef(-100.0f,0.0f,0.0f);
glLoadName(EARTH);
glutSolidSphere(30.0f, 15, 15);
// Draw the Moon
glTranslatef(45.0f, 0.0f, 0.0f);
glRGB(220,220,220);
glPushName(MOON1);
glutSolidSphere(5.0f, 15, 15);glPopName();
glPopMatrix();
// Draw Mars
glRGB(255,0,0);
glPushMatrix();
glTranslatef(100.0f, 0.0f, 0.0f);
glLoadName(MARS);
glutSolidSphere(20.0f, 15, 15);
// Draw Moon1
glTranslatef(-40.0f, 40.0f, 0.0f);
glRGB(220,220,220);
glPushName(MOON1);
glutSolidSphere(5.0f, 15, 15);
glPopName();
// Draw Moon2
glTranslatef(0.0f, -80.0f, 0.0f);
glPushName(MOON2);
glutSolidSphere(5.0f, 15, 15); glPopName();
glPopMatrix();
// Restore the matrix state
glPopMatrix(); // Modelview matrix
glutSwapBuffers();
}
// Parse the selection buffer to see which planet/moon was selected
void ProcessPlanet(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];
// Select on earth or mars, whichever was picked
switch(id)
{
case EARTH:
strcpy(cMessage,"You clicked Earth.");
// If there is another name on the name stack,
// then it must be the moon that was selected
// This is what was actually clicked on
if(count == 2)
strcat(cMessage,"\nSpecifically the moon.");
break;
case MARS:
strcpy(cMessage,"You clicked Mars.");
// We know the name stack is only two deep. The precise
// moon that was selected will be here.
if(count == 2)
{
if(pSelectBuff[4] == MOON1)
strcat(cMessage,"\nSpecifically Moon #1.");
else
strcat(cMessage,"\nSpecifically Moon #2.");
}
break;
// If nothing was clicked we shouldn't be here!
default:
strcpy(cMessage,"Error - Nothing was clicked on!");
break;
}
// Display the message about planet and moon selection
MessageBox(NULL,cMessage,"Selection Message",MB_OK);
}
// 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. Remember OpenGL specifies the
// y coordinate from the bottom, Windows from the top. So windows position
// (as measured from the top) subtract the height and you get it in terms
// OpenGL Likes.
glLoadIdentity();
gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport);
// Apply perspective matrix
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Draw the scene
RenderScene();
// Collect the hits
hits = glRenderMode(GL_RENDER);
// If a single hit occured, display the info.
if(hits == 1)
ProcessPlanet(selectBuff);
// Restore the projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// Go back to modelview for normal rendering
glMatrixMode(GL_MODELVIEW);
}
// Process the mouse click
void MouseCallback(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
ProcessSelection(x, y);
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Light values and coordinates
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
glEnable(GL_CULL_FACE); // Do not calculate insides
// Enable lighting
glEnable(GL_LIGHTING);
// Setup and enable light 0
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);
// Enable color tracking
glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// Black blue background
glClearColor(0.60f, 0.60f, 0.60f, 1.0f );
}
void ChangeSize(int w, int h)
{
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Calculate aspect ratio of the window
fAspect = (GLfloat)w/(GLfloat)h;
// Set the perspective coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Field of view of 45 degrees, near and far planes 1.0 and 425
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Modelview matrix reset
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600,300);
glutCreateWindow("Pick a Planet or Moon");
glutReshapeFunc(ChangeSize);
glutMouseFunc(MouseCallback);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();
return 0;
}
// OpenGL SuperBible, Chapter 14
// Demonstrates OpenGL Hierarchical Selection/Picking
// Program by Richard S. Wright Jr.
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <math.h>
#define glRGB(x, y, z) glColor3ub((GLubyte)x, (GLubyte)y, (GLubyte)z)
#define EARTH 1
#define MARS 2
#define MOON1 3
#define MOON2 4
GLfloat fAspect;
// Lighting values
GLfloat whiteLight[] = { 0.35f, 0.35f, 0.35f, 1.0f };
GLfloat sourceLight[] = { 0.65f, 0.65f, 0.65f, 1.0f };
GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Save the matrix state and do the rotations
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Translate the whole scene out and into view
glTranslatef(0.0f, 0.0f, -300.0f);
// Initialize the names stack
glInitNames();
glPushName(0);
// Draw the Earth
glPushMatrix();
glRGB(0,0,255);
glTranslatef(-100.0f,0.0f,0.0f);
glLoadName(EARTH);
glutSolidSphere(30.0f, 15, 15);
// Draw the Moon
glTranslatef(45.0f, 0.0f, 0.0f);
glRGB(220,220,220);
glPushName(MOON1);
glutSolidSphere(5.0f, 15, 15);glPopName();
glPopMatrix();
// Draw Mars
glRGB(255,0,0);
glPushMatrix();
glTranslatef(100.0f, 0.0f, 0.0f);
glLoadName(MARS);
glutSolidSphere(20.0f, 15, 15);
// Draw Moon1
glTranslatef(-40.0f, 40.0f, 0.0f);
glRGB(220,220,220);
glPushName(MOON1);
glutSolidSphere(5.0f, 15, 15);
glPopName();
// Draw Moon2
glTranslatef(0.0f, -80.0f, 0.0f);
glPushName(MOON2);
glutSolidSphere(5.0f, 15, 15); glPopName();
glPopMatrix();
// Restore the matrix state
glPopMatrix(); // Modelview matrix
glutSwapBuffers();
}
// Parse the selection buffer to see which planet/moon was selected
void ProcessPlanet(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];
// Select on earth or mars, whichever was picked
switch(id)
{
case EARTH:
strcpy(cMessage,"You clicked Earth.");
// If there is another name on the name stack,
// then it must be the moon that was selected
// This is what was actually clicked on
if(count == 2)
strcat(cMessage,"\nSpecifically the moon.");
break;
case MARS:
strcpy(cMessage,"You clicked Mars.");
// We know the name stack is only two deep. The precise
// moon that was selected will be here.
if(count == 2)
{
if(pSelectBuff[4] == MOON1)
strcat(cMessage,"\nSpecifically Moon #1.");
else
strcat(cMessage,"\nSpecifically Moon #2.");
}
break;
// If nothing was clicked we shouldn't be here!
default:
strcpy(cMessage,"Error - Nothing was clicked on!");
break;
}
// Display the message about planet and moon selection
MessageBox(NULL,cMessage,"Selection Message",MB_OK);
}
// 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. Remember OpenGL specifies the
// y coordinate from the bottom, Windows from the top. So windows position
// (as measured from the top) subtract the height and you get it in terms
// OpenGL Likes.
glLoadIdentity();
gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport);
// Apply perspective matrix
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Draw the scene
RenderScene();
// Collect the hits
hits = glRenderMode(GL_RENDER);
// If a single hit occured, display the info.
if(hits == 1)
ProcessPlanet(selectBuff);
// Restore the projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// Go back to modelview for normal rendering
glMatrixMode(GL_MODELVIEW);
}
// Process the mouse click
void MouseCallback(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
ProcessSelection(x, y);
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Light values and coordinates
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
glEnable(GL_CULL_FACE); // Do not calculate insides
// Enable lighting
glEnable(GL_LIGHTING);
// Setup and enable light 0
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);
// Enable color tracking
glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// Black blue background
glClearColor(0.60f, 0.60f, 0.60f, 1.0f );
}
void ChangeSize(int w, int h)
{
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Calculate aspect ratio of the window
fAspect = (GLfloat)w/(GLfloat)h;
// Set the perspective coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Field of view of 45 degrees, near and far planes 1.0 and 425
gluPerspective(45.0f, fAspect, 1.0, 425.0);
// Modelview matrix reset
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600,300);
glutCreateWindow("Pick a Planet or Moon");
glutReshapeFunc(ChangeSize);
glutMouseFunc(MouseCallback);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();
return 0;
}
#11
谢谢!我看过了例子,但是还没找到错误所在,郁闷。。。。。
#12
如果整个场景变换了(平移,缩放,旋转),选择就会出问题,比如物体开始在原点位置,平移之后,还是只能在原先的位置才可以选中,该怎么解决呢?
#13
那不应该,仔细看看投影矩阵和模型矩阵的设置,应该这两个矩阵有问题。
#14
选择部分的代码如下:
{
GLuint selectBuf[SELECT_BUFSIZE];
GLint hits;
GLint viewport[4];
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (SELECT_BUFSIZE, selectBuf);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
(void)glRenderMode(GL_SELECT);
//glInitNames();
//glPushName(0);
glLoadIdentity ();
// 在鼠标位置生成3X3像素区域
gluPickMatrix ((GLdouble)X,(GLdouble)(viewport[3]-(GLint)Y+StatusBar->Height+ToolBar->Height) ,3.0f, 3.0f,viewport);
//gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 1.0, 3001.0); 错误!!!
GLfloat nRange = 10.0;
if (w <= h)
{ glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);}
else
{ glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange); }
glMatrixMode(GL_MODELVIEW);
RenderScene(GL_SELECT);
glMatrixMode (GL_PROJECTION);
glFlush();
hits = glRenderMode (GL_RENDER);
this->Resize();
if(hits){processHits (hits, selectBuf);}
glPopMatrix ();
}
{
GLuint selectBuf[SELECT_BUFSIZE];
GLint hits;
GLint viewport[4];
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (SELECT_BUFSIZE, selectBuf);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
(void)glRenderMode(GL_SELECT);
//glInitNames();
//glPushName(0);
glLoadIdentity ();
// 在鼠标位置生成3X3像素区域
gluPickMatrix ((GLdouble)X,(GLdouble)(viewport[3]-(GLint)Y+StatusBar->Height+ToolBar->Height) ,3.0f, 3.0f,viewport);
//gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 1.0, 3001.0); 错误!!!
GLfloat nRange = 10.0;
if (w <= h)
{ glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);}
else
{ glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange); }
glMatrixMode(GL_MODELVIEW);
RenderScene(GL_SELECT);
glMatrixMode (GL_PROJECTION);
glFlush();
hits = glRenderMode (GL_RENDER);
this->Resize();
if(hits){processHits (hits, selectBuf);}
glPopMatrix ();
}
#15
以上代码中,在投影的时候如果用gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 1.0, 3001.0);
投影,则什么也选不中。
投影,则什么也选不中。
#16
我终于找到了问题所在了,但不知道该怎么解决。问题出在,在FormResize函数中gluPerspective(45.0f, aspect, 1.0, 3001.0);设置了投影之后,紧接着又用gluLookAt函数设置了视点,如果不设置视点,一切正常,设置了视点之后就会出现问题。这该怎么解决呢????????