以下是一個使用 C++ 和 OpenGL 實現滑鼠拾取三角網格的簡單程式碼示例

MarsCactus發表於2024-11-10

以下是一個使用 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 環境已經正確配置並且支援相關的功能。

相關文章