📄 select.c
字号:
// Planets.c
// OpenGL SuperBible, 3rd Edition
// Richard S. Wright Jr.
// rwright@starstonesoftware.com
#include "../../Common/OpenGLSB.h" // System and OpenGL Stuff
#include <math.h>
struct Rectangle
{
int top;
int bottom;
int left;
int right;
};
///////////////////////////
// Object Names
#define TORUS 1
#define SPHERE 2
struct Rectangle boundingRect; // Bounding rectangle
GLuint selectedObject = 0; // Who is selected
float fAspect; // Display aspect ratio
#if !defined(M_PI)
#define M_PI 3.14159265f
#endif
///////////////////////////////////////////////////////////
// Draw a torus (doughnut)
// at z = 0... torus aligns with xy plane
void DrawTorus(int numMajor, int numMinor)
{
float majorRadius = 0.35F;
float minorRadius = 0.15F;
double majorStep = 2.0F*M_PI / numMajor;
double minorStep = 2.0F*M_PI / numMinor;
int i, j;
float c, r, z;
glEnable(GL_NORMALIZE);
for (i=0; i<numMajor; ++i)
{
double a0 = i * majorStep;
double a1 = a0 + majorStep;
GLfloat x0 = (GLfloat) cos(a0);
GLfloat y0 = (GLfloat) sin(a0);
GLfloat x1 = (GLfloat) cos(a1);
GLfloat y1 = (GLfloat) sin(a1);
glBegin(GL_TRIANGLE_STRIP);
for (j=0; j<=numMinor; ++j)
{
double b = j * minorStep;
c = (float) cos(b);
r = minorRadius * c + majorRadius;
z = minorRadius * (GLfloat) sin(b);
glTexCoord2f((float)i/(float)numMajor, (float)j/(float)numMinor);
glNormal3f(x0*c, y0*c, z/minorRadius);
glVertex3f(x0*r, y0*r, z);
glTexCoord2f((float)(i+1)/(float)numMajor, (float)j/(float)numMinor);
glNormal3f(x1*c, y1*c, z/minorRadius);
glVertex3f(x1*r, y1*r, z);
}
glEnd();
}
glDisable(GL_NORMALIZE);
}
///////////////////////////////////////////////////////////
// Just draw a sphere of some given radius
void DrawSphere(float radius)
{
GLUquadricObj *pObj;
pObj = gluNewQuadric();
gluQuadricNormals(pObj, GLU_SMOOTH);
gluSphere(pObj, radius, 26, 13);
gluDeleteQuadric(pObj);
}
///////////////////////////////////////////////////////////
// Render the torus and sphere
void DrawObjects(void)
{
// Save the matrix state and do the rotations
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Translate the whole scene out and into view
glTranslatef(-0.75f, 0.0f, -2.5f);
// Initialize the names stack
glInitNames();
glPushName(0);
// Set material color, Yellow
// torus
glColor3f(1.0f, 1.0f, 0.0f);
glLoadName(TORUS);
glPassThrough((GLfloat)TORUS);
DrawTorus(40, 20);
// Draw Sphere
glColor3f(0.5f, 0.0f, 0.0f);
glTranslatef(1.5f, 0.0f, 0.0f);
glLoadName(SPHERE);
glPassThrough((GLfloat)SPHERE);
DrawSphere(0.5f);
// Restore the matrix state
glPopMatrix(); // Modelview matrix
}
///////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw the objects in the scene
DrawObjects();
// If something is selected, draw a bounding box around it
if(selectedObject != 0)
{
int viewport[4];
// Get the viewport
glGetIntegerv(GL_VIEWPORT, viewport);
// Remap the viewing volume to match window coordinates (approximately)
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// Establish clipping volume (left, right, bottom, top, near, far)
glOrtho(viewport[0], viewport[2], viewport[3], viewport[1], -1, 1);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_LIGHTING);
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_LINE_LOOP);
glVertex2i(boundingRect.left, boundingRect.top);
glVertex2i(boundingRect.left, boundingRect.bottom);
glVertex2i(boundingRect.right, boundingRect.bottom);
glVertex2i(boundingRect.right, boundingRect.top);
glEnd();
glEnable(GL_LIGHTING);
}
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glutSwapBuffers();
}
///////////////////////////////////////////////////////////
// Go into feedback mode and draw a rectangle around the object
#define FEED_BUFF_SIZE 32768
void MakeSelection(int nChoice)
{
// Space for the feedback buffer
static GLfloat feedBackBuff[FEED_BUFF_SIZE];
// Storage for counters, etc.
int size,i,j,count;
// Initial minimum and maximum values
boundingRect.right = boundingRect.bottom = -999999.0f;
boundingRect.left = boundingRect.top = 999999.0f;
// Set the feedback buffer
glFeedbackBuffer(FEED_BUFF_SIZE,GL_2D, feedBackBuff);
// Enter feedback mode
glRenderMode(GL_FEEDBACK);
// Redraw the scene
DrawObjects();
// Leave feedback mode
size = glRenderMode(GL_RENDER);
// Parse the feedback buffer and get the
// min and max X and Y window coordinates
i = 0;
while(i < size)
{
// Search for appropriate token
if(feedBackBuff[i] == GL_PASS_THROUGH_TOKEN)
if(feedBackBuff[i+1] == (GLfloat)nChoice)
{
i+= 2;
// Loop until next token is reached
while(i < size && feedBackBuff[i] != GL_PASS_THROUGH_TOKEN)
{
// Just get the polygons
if(feedBackBuff[i] == GL_POLYGON_TOKEN)
{
// Get all the values for this polygon
count = (int)feedBackBuff[++i]; // How many vertices
i++;
for(j = 0; j < count; j++) // Loop for each vertex
{
// Min and Max X
if(feedBackBuff[i] > boundingRect.right)
boundingRect.right = feedBackBuff[i];
if(feedBackBuff[i] < boundingRect.left)
boundingRect.left = feedBackBuff[i];
i++;
// Min and Max Y
if(feedBackBuff[i] > boundingRect.bottom)
boundingRect.bottom = feedBackBuff[i];
if(feedBackBuff[i] < boundingRect.top)
boundingRect.top = feedBackBuff[i];
i++;
}
}
else
i++; // Get next index and keep looking
}
break;
}
i++;
}
}
///////////////////////////////////////////////////////////
// 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
static GLuint selectBuff[BUFFER_LENGTH];
// Hit counter and viewport storage
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 horizontal direction
glLoadIdentity();
gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport);
// Apply perspective matrix
gluPerspective(60.0f, fAspect, 1.0, 425.0);
// Draw the scene
DrawObjects();
// Collect the hits
hits = glRenderMode(GL_RENDER);
// Restore the projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// Go back to modelview for normal rendering
glMatrixMode(GL_MODELVIEW);
// If a single hit occurred, display the info.
if(hits == 1)
{
MakeSelection(selectBuff[3]);
if(selectedObject == selectBuff[3])
selectedObject = 0;
else
selectedObject = selectBuff[3];
}
glutPostRedisplay();
}
///////////////////////////////////////////////////////////
// This function does any needed initialization on the rendering
// context. Here it sets up and initializes the lighting for
// the scene.
void SetupRC()
{
// Lighting values
GLfloat dimLight[] = { 0.1f, 0.1f, 0.1f, 1.0f };
GLfloat sourceLight[] = { 0.65f, 0.65f, 0.65f, 1.0f };
GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
// 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
glLightfv(GL_LIGHT0,GL_AMBIENT,dimLight);
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);
// Gray background
glClearColor(0.60f, 0.60f, 0.60f, 1.0f );
glLineWidth(2.0f);
}
///////////////////////////////////////////////////////////
// Set viewport and projection
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(60.0f, fAspect, 1.0, 425.0);
// Modelview matrix reset
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
///////////////////////////////////////////////////////////
// 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);
}
///////////////////////////////////////////////////////////
// Program entry point
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800,600);
glutCreateWindow("Select an Object");
glutReshapeFunc(ChangeSize);
glutMouseFunc(MouseCallback);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -