opengl 鼠标捡选(可漫游,gluPickMatrix)

该博客介绍了如何使用OpenGL实现鼠标点击选择3D场景中的对象(如太阳系行星),并提供了相应的代码示例。通过gluPickMatrix和gluPerspective进行视口变换和投影,实现精确的鼠标选择。当鼠标点击时,通过ProcessSelection函数处理选择,显示所选物体的信息。此外,还展示了如何处理窗口大小改变以保持正确的透视效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//参照opengl超级宝典的planets源程序

#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;


// Called to draw scene
void RenderScene(void)
 {
 // Clear the window with current clearing color
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//此处可加gluLookAt()函数

 // 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)
 {
  int choose = selectBuff[3];
  int depth = selectBuff[1];

  for(int i = 0 ; i < hits ; i++)
  {
   if(selectBuff[i*4 + 1] < (GLuint)depth)//获取深度最小的物体(selectBuff是按照ID从小到大排列的)
   {
    choose = selectBuff[i*4 + 3];
    depth  = selectBuff[i*4 + 1];
   }
  }
  
   ProcessPlanet( choose);
  
 }

 // 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);
 }

 

 

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);
 
 glutMainLoop();

 return 0;
 }

注意:
1.ProcessSelection()函数中的gluPerspective(45.0f, fAspect, 1.0, 425.0);的参数必须与ChangeSize()函数内的gluPerspective参数一致,否则会不匹配.
2.gluPickMatrix选出的矩阵数组里的元素是按ID号逐渐增大排列的.

内容概要:文章详细介绍了电梯门禁(梯控)系统的硬件安装与接线要点。首先强调了梯控板与楼层按键对接的重要性,包括遵循一一对应原则以避免错层、越层问题,允许空层存在以适应实际需求。接着阐述了不同接线方式(COM、NO、NC端口的不同组合)对用户权限的影响,如单层权限用户刷卡直达指定楼层,多层权限用户在特定接线方式下的操作限制。硬件安装方面,强调了无源干触点设计原则以确保电气隔离,防止系统间干扰,以及读卡器接入时的规范要求。文章还介绍了梯控系统的技术原理,如身份验证机制(二维码/IC卡/人脸识别)、消防联动功能(紧急情况下释放所有楼层权限),并指出该系统适用于小区、写字楼等场景,支持机器人乘梯SDK扩展。最后,根据不同场景需求提出了适用的接线方式择,如严格管控场景下择4.3接线以实现精准权限控制,限制多层用户手动层场景下择4.1接线并配合软件权限设置。; 适合人群:从事电梯安装维护的技术人员、楼宇自动化工程师及相关领域的管理人员。; 使用场景及目标:①指导技术人员正确安装和接线梯控系统,确保系统安全稳定运行;②帮助管理人员了解不同接线方式对用户权限的影响,以便根据实际需求择合适的配置方案;③提升楼宇安全管理和服务质量,特别是在小区、写字楼等场所的应用。; 其他说明:梯控系统的正确安装和接线不仅关系到系统的正常运作,更直接影响到用户的安全和使用体验。因此,在实际操作中务必严格按照规范执行,同时关注最新的技术发展和应用场景变化,以确保系统始终处于最佳状态。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值