以下是一个使用 C++ 和 OpenGL 实现鼠标拾取三角网格的简单代码示例

以下是一个使用 C++ 和 OpenGL 实现鼠标拾取三角网格的简单代码示例:

#include <GL/glut.h>
#include <iostream>
#include <vector>

// 存储三角网格的顶点信息
struct Triangle {
    GLfloat vertices[9];
};

// 存储三角网格的列表
std::vector<Triangle> triangles;

// 初始化 OpenGL 环境和三角网格数据
void init() {
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, 1.0, 0.1, 100.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // 创建一些简单的三角网格数据(这里只是示例,你可以根据实际情况读取或生成更复杂的三角网格)
    Triangle t1 = {
            {0.0f, 0.5f, 0.0f,
             0.5f, -0.5f, 0.0f,
             -0.5f, -0.5f, 0.0f}
    };
    Triangle t2 = {
            {1.0f, 1.0f, 0.0f,
             1.5f, 0.0f, 0.0f,
             0.5f, 0.0f, 0.0f}
    };
    triangles.push_back(t1);
    triangles.push_back(t2);
}

// 绘制三角网格
void drawTriangles() {
    glBegin(GL_TRIANGLES);
    for (const auto &triangle : triangles) {
        for (int i = 0; i < 9; i += 3) {
            glVertex3f(triangle.vertices[i], triangle.vertices[i + 1], triangle.vertices[i + 2]);
        }
    }
    glEnd();
}

// 鼠标点击事件处理函数
void mouseClick(int button, int state, int x, int y) {
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
        // 进入选择模式
        GLint viewport[4];
        glGetIntegerv(GL_VIEWPORT, viewport);

        GLuint selectBuffer[512];
        glSelectBuffer(512, selectBuffer);
        glRenderMode(GL_SELECT);

        glInitNames();
        glPushName(0);

        // 保存当前的投影矩阵和模型视图矩阵
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        gluPickMatrix(x, viewport[3] - y, 5, 5, viewport);
        gluPerspective(45.0, (GLfloat) viewport[2] / viewport[3], 0.1, 100.0);

        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();

        // 重新绘制场景用于选择
        drawTriangles();

        // 恢复原来的矩阵模式
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();

        // 返回渲染模式
        GLint numHits = glRenderMode(GL_RENDER);

        if (numHits > 0) {
            GLuint *ptr = selectBuffer;
            for (int i = 0; i < numHits; ++i) {
                int names = *ptr++;
                int minZ = *ptr++;
                int maxZ = *ptr++;
                // 这里可以根据你的需求处理每个选中的物体
                std::cout << "Hit " << i + 1 << ", " << names << " objects were picked." << std::endl;
            }
        }
    }
}

// 显示函数,用于绘制场景
void display() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

    // 绘制三角网格
    drawTriangles();

    glutSwapBuffers();
}

int main(int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Triangle Picking Example");

    init();
    glutMouseFunc(mouseClick);
    glutDisplayFunc(display);

    glutMainLoop();
    return 0;
}

在上述代码中:

  1. init 函数用于初始化 OpenGL 环境,设置背景颜色、投影矩阵和模型视图矩阵等。同时创建了一些简单的三角网格数据用于测试。
  2. drawTriangles 函数用于绘制所有的三角网格。
  3. mouseClick 函数是鼠标点击事件的处理函数。当鼠标左键按下时,进入选择模式,设置选择缓冲区,保存当前的投影矩阵和模型视图矩阵,然后重新绘制场景用于选择。最后,根据选择缓冲区中的信息确定选中的物体。
  4. display 函数用于在正常渲染模式下绘制场景,包括三角网格。

请注意,这只是一个简单的示例,在实际应用中,你可能需要根据具体的需求对代码进行进一步的扩展和优化,例如处理更复杂的场景、更精确的选择等。同时,确保你的 OpenGL 环境已经正确配置并且支持相关的功能。

posted @ 2024-11-10 00:45  MarsCactus  阅读(17)  评论(0编辑  收藏  举报