雏形

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <vector>
#include <string>

// 窗口尺寸
const unsigned int SCR_WIDTH = 1280;
const unsigned int SCR_HEIGHT = 720;

// 菜单栏常量
const int MENU_HEIGHT = 30;
const int MENU_ITEM_WIDTH = 100;

// 相机参数
glm::vec3 cameraPos = glm::vec3(0.0f, 50.0f, 150.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
float yaw = -90.0f;    // 偏航角
float pitch = 0.0f;    // 俯仰角
float fov = 75.0f;     // 视野角
bool firstMouse = true;
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
float deltaTime = 0.0f;
float lastFrame = 0.0f;
bool mousePressed = false;
bool isDragging = false;
glm::vec2 dragStart;

// 菜单状态
enum MenuItem {
    MENU_NONE,
    MENU_FILE,
    MENU_VIEW,
    MENU_HELP
};

enum FileSubmenu {
    FILE_NONE,
    FILE_NEW,
    FILE_EXIT
};

enum ViewSubmenu {
    VIEW_NONE,
    VIEW_RESET_CAMERA,
    VIEW_WIREFRAME,
    VIEW_SOLID
};

MenuItem activeMenu = MENU_NONE;
FileSubmenu activeFileSubmenu = FILE_NONE;
ViewSubmenu activeViewSubmenu = VIEW_NONE;
bool wireframeMode = false;

// 物体选择相关
enum SelectedObject {
    SELECT_NONE,
    SELECT_DAM,
    SELECT_WATER,
    SELECT_MOUNTAIN
};
SelectedObject selectedObject = SELECT_NONE;
std::string objectInfo = "未选择任何物体";

// 鼠标回调函数
void mouseCallback(GLFWwindow* window, double xpos, double ypos) {
    // 检查是否在菜单栏区域
    if (ypos < MENU_HEIGHT) {
        // 处理菜单鼠标移动
        int x = static_cast<int>(xpos);
        int y = static_cast<int>(ypos);
        
        if (mousePressed) {
            // 处理菜单点击
            if (x < MENU_ITEM_WIDTH) {
                activeMenu = MENU_FILE;
                activeViewSubmenu = VIEW_NONE;
            } else if (x < 2 * MENU_ITEM_WIDTH) {
                activeMenu = MENU_VIEW;
                activeFileSubmenu = FILE_NONE;
            } else if (x < 3 * MENU_ITEM_WIDTH) {
                activeMenu = MENU_HELP;
                activeFileSubmenu = FILE_NONE;
                activeViewSubmenu = VIEW_NONE;
            } else {
                activeMenu = MENU_NONE;
                activeFileSubmenu = FILE_NONE;
                activeViewSubmenu = VIEW_NONE;
            }
        }
        return;
    }

    // 处理3D场景鼠标交互
    if (firstMouse) {
        lastX = xpos;
        lastY = ypos;
        firstMouse = false;
    }

    if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) {
        if (!isDragging) {
            isDragging = true;
            dragStart = glm::vec2(xpos, ypos);
        } else {
            float xoffset = xpos - lastX;
            float yoffset = lastY - ypos;
            lastX = xpos;
            lastY = ypos;

            float sensitivity = 0.1f;
            xoffset *= sensitivity;
            yoffset *= sensitivity;

            yaw += xoffset;
            pitch += yoffset;

            if (pitch > 89.0f) pitch = 89.0f;
            if (pitch < -89.0f) pitch = -89.0f;

            glm::vec3 front;
            front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
            front.y = sin(glm::radians(pitch));
            front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
            cameraFront = glm::normalize(front);
        }
    } else {
        if (isDragging) {
            isDragging = false;
            // 检测点击选择(简化版)
            glm::vec2 dragEnd(xpos, ypos);
            if (glm::length(dragEnd - dragStart) < 5.0f) {
                // 这里使用简单的位置判断模拟射线检测
                float clickX = (2.0f * xpos) / SCR_WIDTH - 1.0f;
                float clickY = 1.0f - (2.0f * ypos) / SCR_HEIGHT;
                
                // 简化的物体选择逻辑
                if (clickY > -0.5f && clickY < 0.5f && clickX > -0.3f && clickX < 0.3f) {
                    selectedObject = SELECT_DAM;
                    objectInfo = "大坝: 混凝土结构,高度50米";
                } else if (clickY < -0.2f && clickX > -0.6f && clickX < 0.6f) {
                    selectedObject = SELECT_WATER;
                    objectInfo = "水体: 库容约500万立方米";
                } else if ((clickX < -0.5f || clickX > 0.5f) && clickY < 0.3f) {
                    selectedObject = SELECT_MOUNTAIN;
                    objectInfo = "山体: 岩石结构,高度80米";
                } else {
                    selectedObject = SELECT_NONE;
                    objectInfo = "未选择任何物体";
                }
            }
        }
        firstMouse = true;
    }
}

// 鼠标按钮回调
void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods) {
    if (button == GLFW_MOUSE_BUTTON_LEFT) {
        if (action == GLFW_PRESS) {
            mousePressed = true;
        } else if (action == GLFW_RELEASE) {
            mousePressed = false;
            
            // 检查子菜单点击
            double xpos, ypos;
            glfwGetCursorPos(window, &xpos, &ypos);
            int x = static_cast<int>(xpos);
            int y = static_cast<int>(ypos);
            
            if (activeMenu == MENU_FILE && y > MENU_HEIGHT && y < MENU_HEIGHT + 30 * 2) {
                if (x < MENU_ITEM_WIDTH) {
                    if (y < MENU_HEIGHT + 30) {
                        activeFileSubmenu = FILE_NEW;
                        // 重置场景
                        cameraPos = glm::vec3(0.0f, 50.0f, 150.0f);
                        cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
                        yaw = -90.0f;
                        pitch = 0.0f;
                        fov = 75.0f;
                        selectedObject = SELECT_NONE;
                        objectInfo = "未选择任何物体";
                    } else {
                        activeFileSubmenu = FILE_EXIT;
                        glfwSetWindowShouldClose(window, true);
                    }
                }
            } else if (activeMenu == MENU_VIEW && y > MENU_HEIGHT && y < MENU_HEIGHT + 30 * 3) {
                if (x < MENU_ITEM_WIDTH) {
                    if (y < MENU_HEIGHT + 30) {
                        activeViewSubmenu = VIEW_RESET_CAMERA;
                        cameraPos = glm::vec3(0.0f, 50.0f, 150.0f);
                        cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
                        yaw = -90.0f;
                        pitch = 0.0f;
                        fov = 75.0f;
                    } else if (y < MENU_HEIGHT + 60) {
                        activeViewSubmenu = VIEW_WIREFRAME;
                        wireframeMode = true;
                        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
                    } else {
                        activeViewSubmenu = VIEW_SOLID;
                        wireframeMode = false;
                        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
                    }
                }
            }
            
            // 点击其他区域关闭菜单
            if (y > MENU_HEIGHT + 30 || x > MENU_ITEM_WIDTH * (activeMenu == MENU_FILE ? 1 : 1)) {
                activeMenu = MENU_NONE;
                activeFileSubmenu = FILE_NONE;
                activeViewSubmenu = VIEW_NONE;
            }
        }
    }
}

// 滚轮回调函数
void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
    fov -= (float)yoffset;
    if (fov < 1.0f) fov = 1.0f;
    if (fov > 120.0f) fov = 120.0f;
}

// 处理键盘输入
void processInput(GLFWwindow* window) {
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);

    float cameraSpeed = 2.5f * deltaTime;
    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        cameraPos += cameraSpeed * cameraFront;
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        cameraPos -= cameraSpeed * cameraFront;
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
        cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
        cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
    if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
        cameraPos += cameraSpeed * cameraUp;
    if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
        cameraPos -= cameraSpeed * cameraUp;
}

// 编译着色器
unsigned int compileShader(unsigned int type, const char* source) {
    unsigned int id = glCreateShader(type);
    glShaderSource(id, 1, &source, nullptr);
    glCompileShader(id);

    int result;
    glGetShaderiv(id, GL_COMPILE_STATUS, &result);
    if (result == GL_FALSE) {
        int length;
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
        char* message = (char*)alloca(length * sizeof(char));
        glGetShaderInfoLog(id, length, &length, message);
        std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader!" << std::endl;
        std::cout << message << std::endl;
        glDeleteShader(id);
        return 0;
    }

    return id;
}

// 创建着色器程序
unsigned int createShaderProgram(const char* vertexSource, const char* fragmentSource) {
    unsigned int vertexShader = compileShader(GL_VERTEX_SHADER, vertexSource);
    unsigned int fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentSource);

    unsigned int program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    glLinkProgram(program);

    int result;
    glGetProgramiv(program, GL_LINK_STATUS, &result);
    if (result == GL_FALSE) {
        int length;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
        char* message = (char*)alloca(length * sizeof(char));
        glGetProgramInfoLog(program, length, &length, message);
        std::cout << "Failed to link shader program!" << std::endl;
        std::cout << message << std::endl;
        glDeleteProgram(program);
        return 0;
    }

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    return program;
}

// 创建立方体
unsigned int createCube(float width, float height, float depth, const glm::vec3& color) {
    float w = width / 2.0f;
    float h = height / 2.0f;
    float d = depth / 2.0f;

    float vertices[] = {
        // 位置                // 颜色
        -w, -h, -d,  color.r, color.g, color.b,
         w, -h, -d,  color.r, color.g, color.b,
         w,  h, -d,  color.r, color.g, color.b,
         w,  h, -d,  color.r, color.g, color.b,
        -w,  h, -d,  color.r, color.g, color.b,
        -w, -h, -d,  color.r, color.g, color.b,

        -w, -h,  d,  color.r, color.g, color.b,
         w, -h,  d,  color.r, color.g, color.b,
         w,  h,  d,  color.r, color.g, color.b,
         w,  h,  d,  color.r, color.g, color.b,
        -w,  h,  d,  color.r, color.g, color.b,
        -w, -h,  d,  color.r, color.g, color.b,

        -w,  h,  d,  color.r, color.g, color.b,
        -w,  h, -d,  color.r, color.g, color.b,
        -w, -h, -d,  color.r, color.g, color.b,
        -w, -h, -d,  color.r, color.g, color.b,
        -w, -h,  d,  color.r, color.g, color.b,
        -w,  h,  d,  color.r, color.g, color.b,

         w,  h,  d,  color.r, color.g, color.b,
         w,  h, -d,  color.r, color.g, color.b,
         w, -h, -d,  color.r, color.g, color.b,
         w, -h, -d,  color.r, color.g, color.b,
         w, -h,  d,  color.r, color.g, color.b,
         w,  h,  d,  color.r, color.g, color.b,

        -w, -h, -d,  color.r, color.g, color.b,
         w, -h, -d,  color.r, color.g, color.b,
         w, -h,  d,  color.r, color.g, color.b,
         w, -h,  d,  color.r, color.g, color.b,
        -w, -h,  d,  color.r, color.g, color.b,
        -w, -h, -d,  color.r, color.g, color.b,

        -w,  h, -d,  color.r, color.g, color.b,
         w,  h, -d,  color.r, color.g, color.b,
         w,  h,  d,  color.r, color.g, color.b,
         w,  h,  d,  color.r, color.g, color.b,
        -w,  h,  d,  color.r, color.g, color.b,
        -w,  h, -d,  color.r, color.g, color.b
    };

    unsigned int VAO, VBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 位置属性
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    
    // 颜色属性
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    return VAO;
}

// 创建平面
unsigned int createPlane(float width, float height, const glm::vec3& color) {
    float w = width / 2.0f;
    float h = height / 2.0f;

    float vertices[] = {
        // 位置                // 颜色
        -w, 0.0f, -h,  color.r, color.g, color.b,
         w, 0.0f, -h,  color.r, color.g, color.b,
         w, 0.0f,  h,  color.r, color.g, color.b,
         w, 0.0f,  h,  color.r, color.g, color.b,
        -w, 0.0f,  h,  color.r, color.g, color.b,
        -w, 0.0f, -h,  color.r, color.g, color.b
    };

    unsigned int VAO, VBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 位置属性
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    
    // 颜色属性
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    return VAO;
}

// 创建锥体(简化版山体)
unsigned int createCone(float radius, float height, int segments, const glm::vec3& color) {
    std::vector<float> vertices;

    // 底部中心
    vertices.insert(vertices.end(), {0.0f, 0.0f, 0.0f, color.r, color.g, color.b});

    // 底部边缘
    for (int i = 0; i < segments; i++) {
        float angle = 2.0f * glm::pi<float>() * (float)i / (float)segments;
        float x = radius * cos(angle);
        float z = radius * sin(angle);
        vertices.insert(vertices.end(), {x, 0.0f, z, color.r, color.g, color.b});
    }

    // 顶部点
    vertices.insert(vertices.end(), {0.0f, height, 0.0f, color.r, color.g, color.b});

    // 底部三角形
    for (int i = 0; i < segments; i++) {
        int next = (i + 1) % segments;
        vertices.insert(vertices.end(), {
            0.0f, 0.0f, 0.0f, color.r, color.g, color.b,
            radius * cos(2.0f * glm::pi<float>() * (float)next / (float)segments), 0.0f, radius * sin(2.0f * glm::pi<float>() * (float)next / (float)segments), color.r, color.g, color.b,
            radius * cos(2.0f * glm::pi<float>() * (float)i / (float)segments), 0.0f, radius * sin(2.0f * glm::pi<float>() * (float)i / (float)segments), color.r, color.g, color.b
        });
    }

    // 侧面三角形
    for (int i = 0; i < segments; i++) {
        int next = (i + 1) % segments;
        vertices.insert(vertices.end(), {
            0.0f, height, 0.0f, color.r, color.g, color.b,
            radius * cos(2.0f * glm::pi<float>() * (float)i / (float)segments), 0.0f, radius * sin(2.0f * glm::pi<float>() * (float)i / (float)segments), color.r, color.g, color.b,
            radius * cos(2.0f * glm::pi<float>() * (float)next / (float)segments), 0.0f, radius * sin(2.0f * glm::pi<float>() * (float)next / (float)segments), color.r, color.g, color.b
        });
    }

    unsigned int VAO, VBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW);

    // 位置属性
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    
    // 颜色属性
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    return VAO;
}

// 渲染2D矩形(用于菜单)
void renderRect(float x, float y, float width, float height, const glm::vec3& color, unsigned int shaderProgram) {
    float vertices[] = {
        x, y, 0.0f, color.r, color.g, color.b,
        x + width, y, 0.0f, color.r, color.g, color.b,
        x + width, y + height, 0.0f, color.r, color.g, color.b,
        x + width, y + height, 0.0f, color.r, color.g, color.b,
        x, y + height, 0.0f, color.r, color.g, color.b,
        x, y, 0.0f, color.r, color.g, color.b
    };

    unsigned int VAO, VBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    glDrawArrays(GL_TRIANGLES, 0, 6);

    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
}

// 渲染菜单
void renderMenu(unsigned int shaderProgram) {
    // 保存当前矩阵状态
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrtho(0, SCR_WIDTH, SCR_HEIGHT, 0, -1, 1);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

    // 禁用深度测试以正确显示UI
    glDisable(GL_DEPTH_TEST);

    // 渲染主菜单条
    renderRect(0, 0, SCR_WIDTH, MENU_HEIGHT, glm::vec3(0.3f, 0.3f, 0.3f), shaderProgram);
    
    // 渲染菜单项
    renderRect(0, 0, MENU_ITEM_WIDTH, MENU_HEIGHT, glm::vec3(0.4f, 0.4f, 0.4f), shaderProgram);
    renderRect(MENU_ITEM_WIDTH, 0, MENU_ITEM_WIDTH, MENU_HEIGHT, glm::vec3(0.4f, 0.4f, 0.4f), shaderProgram);
    renderRect(2 * MENU_ITEM_WIDTH, 0, MENU_ITEM_WIDTH, MENU_HEIGHT, glm::vec3(0.4f, 0.4f, 0.4f), shaderProgram);

    // 恢复着色器程序的模型矩阵
    glm::mat4 model = glm::mat4(1.0f);
    glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
    glm::mat4 view = glm::mat4(1.0f);
    glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));
    glm::mat4 projection = glm::ortho(0.0f, (float)SCR_WIDTH, (float)SCR_HEIGHT, 0.0f, -1.0f, 1.0f);
    glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));

    // 渲染文件子菜单
    if (activeMenu == MENU_FILE) {
        renderRect(0, MENU_HEIGHT, MENU_ITEM_WIDTH, 60, glm::vec3(0.4f, 0.4f, 0.4f), shaderProgram);
        renderRect(0, MENU_HEIGHT, MENU_ITEM_WIDTH, 30, glm::vec3(0.5f, 0.5f, 0.5f), shaderProgram);
        renderRect(0, MENU_HEIGHT + 30, MENU_ITEM_WIDTH, 30, glm::vec3(0.5f, 0.5f, 0.5f), shaderProgram);
    }
    
    // 渲染视图子菜单
    if (activeMenu == MENU_VIEW) {
        renderRect(MENU_ITEM_WIDTH, MENU_HEIGHT, MENU_ITEM_WIDTH, 90, glm::vec3(0.4f, 0.4f, 0.4f), shaderProgram);
        renderRect(MENU_ITEM_WIDTH, MENU_HEIGHT, MENU_ITEM_WIDTH, 30, glm::vec3(0.5f, 0.5f, 0.5f), shaderProgram);
        renderRect(MENU_ITEM_WIDTH, MENU_HEIGHT + 30, MENU_ITEM_WIDTH, 30, glm::vec3(0.5f, 0.5f, 0.5f), shaderProgram);
        renderRect(MENU_ITEM_WIDTH, MENU_HEIGHT + 60, MENU_ITEM_WIDTH, 30, glm::vec3(0.5f, 0.5f, 0.5f), shaderProgram);
    }

    // 渲染帮助子菜单
    if (activeMenu == MENU_HELP) {
        renderRect(2 * MENU_ITEM_WIDTH, MENU_HEIGHT, MENU_ITEM_WIDTH, 30, glm::vec3(0.4f, 0.4f, 0.4f), shaderProgram);
    }

    // 渲染物体信息面板
    renderRect(SCR_WIDTH - 300, MENU_HEIGHT, 300, 30, glm::vec3(0.2f, 0.2f, 0.2f), shaderProgram);

    // 恢复深度测试
    glEnable(GL_DEPTH_TEST);

    // 恢复矩阵状态
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
}

int main() {
    // 初始化GLFW
    if (!glfwInit()) {
        std::cerr << "Failed to initialize GLFW" << std::endl;
        return -1;
    }

    // 设置OpenGL版本
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "大坝3D模型", NULL, NULL);
    if (!window) {
        std::cerr << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 设置回调函数
    glfwSetCursorPosCallback(window, mouseCallback);
    glfwSetMouseButtonCallback(window, mouseButtonCallback);
    glfwSetScrollCallback(window, scrollCallback);
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);

    // 初始化GLEW
    if (glewInit() != GLEW_OK) {
        std::cerr << "Failed to initialize GLEW" << std::endl;
        return -1;
    }

    // 启用深度测试
    glEnable(GL_DEPTH_TEST);
    // 启用混合(用于半透明效果)
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    // 顶点着色器代码
    const char* vertexShaderSource = "#version 330 core\n"
        "layout (location = 0) in vec3 aPos;\n"
        "layout (location = 1) in vec3 aColor;\n"
        "out vec3 ourColor;\n"
        "uniform mat4 model;\n"
        "uniform mat4 view;\n"
        "uniform mat4 projection;\n"
        "void main()\n"
        "{\n"
        "   gl_Position = projection * view * model * vec4(aPos, 1.0);\n"
        "   ourColor = aColor;\n"
        "}\0";

    // 片段着色器代码
    const char* fragmentShaderSource = "#version 330 core\n"
        "in vec3 ourColor;\n"
        "out vec4 FragColor;\n"
        "void main()\n"
        "{\n"
        "   FragColor = vec4(ourColor, 1.0);\n"
        "}\0";

    // 创建着色器程序
    unsigned int shaderProgram = createShaderProgram(vertexShaderSource, fragmentShaderSource);
    if (!shaderProgram) return -1;

    // 创建场景元素
    // 地面
    unsigned int groundVAO = createPlane(500, 500, glm::vec3(0.545f, 0.271f, 0.075f)); // 棕色

    // 水体
    unsigned int waterVAO = createPlane(300, 200, glm::vec3(0.275f, 0.509f, 0.706f)); // 钢蓝色

    // 左侧山体
    unsigned int leftMountainVAO = createCone(100, 80, 4, glm::vec3(0.133f, 0.545f, 0.133f)); // 绿色

    // 右侧山体
    unsigned int rightMountainVAO = createCone(100, 70, 4, glm::vec3(0.133f, 0.545f, 0.133f)); // 绿色

    // 远处山体
    unsigned int farMountainVAO = createCone(135, 50, 4, glm::vec3(0.133f, 0.4f, 0.133f)); // 深绿色

    // 大坝基础
    unsigned int damBaseVAO = createCube(100, 20, 40, glm::vec3(0.533f, 0.533f, 0.533f)); // 灰色

    // 大坝正面倾斜部分
    unsigned int damSlopeVAO = createCube(100, 30, 20, glm::vec3(0.533f, 0.533f, 0.533f)); // 灰色

    // 坝顶结构
    unsigned int damTopVAO = createCube(100, 5, 10, glm::vec3(0.533f, 0.533f, 0.533f)); // 灰色

    // 水闸塔(使用浅灰色)
    glm::vec3 towerColor = glm::vec3(0.8f, 0.8f, 0.8f);
    unsigned int leftTower1VAO = createCube(6, 20, 10, towerColor);
    unsigned int leftTower2VAO = createCube(6, 20, 10, towerColor);
    unsigned int centerTower1VAO = createCube(6, 25, 10, towerColor);
    unsigned int centerTower2VAO = createCube(6, 25, 10, towerColor);
    unsigned int rightTower1VAO = createCube(6, 20, 10, towerColor);
    unsigned int rightTower2VAO = createCube(6, 20, 10, towerColor);

    // 右侧建筑
    unsigned int rightBuildingVAO = createCube(15, 15, 10, towerColor);

    // 渲染循环
    while (!glfwWindowShouldClose(window)) {
        // 计算时间差
        float currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        // 处理输入
        processInput(window);

        // 清空颜色缓冲和深度缓冲
        glClearColor(0.533f, 0.808f, 0.922f, 1.0f); // 天空蓝
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // 使用着色器程序
        glUseProgram(shaderProgram);

        // 视图矩阵
        glm::mat4 view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));

        // 投影矩阵
        glm::mat4 projection = glm::perspective(glm::radians(fov), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 2000.0f);
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));

        // 绘制地面
        glm::mat4 model = glm::mat4(1.0f);
        model = glm::rotate(model, glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(groundVAO);
        glDrawArrays(GL_TRIANGLES, 0, 6);

        // 绘制远处山体
        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(0, 0, -200));
        model = glm::rotate(model, glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
        model = glm::rotate(model, glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(farMountainVAO);
        glDrawArrays(GL_TRIANGLES, 0, 4*3 + 4*3); // 底部4个三角形 + 侧面4个三角形

        // 绘制左侧山体
        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(-150, 20, -50));
        model = glm::rotate(model, glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
        model = glm::rotate(model, glm::radians(45.0f), glm::vec3(0.0f, 1.0f, 0.0f));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(leftMountainVAO);
        glDrawArrays(GL_TRIANGLES, 0, 4*3 + 4*3);

        // 绘制右侧山体
        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(150, 15, -50));
        model = glm::rotate(model, glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
        model = glm::rotate(model, glm::radians(-45.0f), glm::vec3(0.0f, 1.0f, 0.0f));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(rightMountainVAO);
        glDrawArrays(GL_TRIANGLES, 0, 4*3 + 4*3);

        // 绘制水体(半透明)
        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(0, 5, -100));
        model = glm::rotate(model, glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(waterVAO);
        glDrawArrays(GL_TRIANGLES, 0, 6);

        // 绘制大坝基础
        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(0, 10, 0));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(damBaseVAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        // 绘制大坝倾斜部分
        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(0, 25, -10));
        model = glm::rotate(model, glm::radians(-17.19f), glm::vec3(1.0f, 0.0f, 0.0f)); // -0.3弧度 ≈ -17.19度
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(damSlopeVAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        // 绘制坝顶结构
        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(0, 30, 20));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(damTopVAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        // 绘制水闸塔
        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(-30, 40, 20));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(leftTower1VAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(-15, 40, 20));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(leftTower2VAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(-5, 45, 20));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(centerTower1VAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(5, 45, 20));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(centerTower2VAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(15, 40, 20));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(rightTower1VAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(30, 40, 20));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(rightTower2VAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        // 绘制右侧建筑
        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(55, 35, 20));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glBindVertexArray(rightBuildingVAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        // 渲染菜单
        renderMenu(shaderProgram);

        // 交换缓冲并轮询事件
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // 清理资源
    glDeleteVertexArrays(1, &groundVAO);
    glDeleteVertexArrays(1, &waterVAO);
    glDeleteVertexArrays(1, &leftMountainVAO);
    glDeleteVertexArrays(1, &rightMountainVAO);
    glDeleteVertexArrays(1, &farMountainVAO);
    glDeleteVertexArrays(1, &damBaseVAO);
    glDeleteVertexArrays(1, &damSlopeVAO);
    glDeleteVertexArrays(1, &damTopVAO);
    glDeleteVertexArrays(1, &leftTower1VAO);
    glDeleteVertexArrays(1, &leftTower2VAO);
    glDeleteVertexArrays(1, &centerTower1VAO);
    glDeleteVertexArrays(1, &centerTower2VAO);
    glDeleteVertexArrays(1, &rightTower1VAO);
    glDeleteVertexArrays(1, &rightTower2VAO);
    glDeleteVertexArrays(1, &rightBuildingVAO);
    glDeleteProgram(shaderProgram);

    // 终止GLFW
    glfwTerminate();
    return 0;
}

  

posted @ 2025-09-24 17:07  华腾智算  阅读(9)  评论(0)    收藏  举报
https://damo.alibaba.com/ https://tianchi.aliyun.com/course?spm=5176.21206777.J_3941670930.5.87dc17c9BZNvLL