cpp文件CandyRenderEngine/Math/Transform.cpp

OpenTK 2026-05-07 17:43:54

cpp文件CandyRenderEngine/Math/Transform.cpp
//===========================================================
// 文件: Transform.cpp
// 路径: CandyRenderEngine/Math/Transform.cpp
// 说明: 变换组件实现文件,实现平移、旋转、缩放的具体逻辑
// 依赖: Transform.h, GLM 数学库
//===========================================================

#include "pch.h"
#include "Transform.h"
#include <cmath>

Transform::Transform() {
    Reset();
}

// ===== 平移 =====
void Transform::SetPosition(const glm::vec3& position) {
    m_Position = position;
}

void Transform::SetPosition(float x, float y, float z) {
    m_Position = glm::vec3(x, y, z);
}

void Transform::Translate(const glm::vec3& delta) {
    m_Position += delta;
}

void Transform::Translate(float x, float y, float z) {
    m_Position += glm::vec3(x, y, z);
}

// ===== 旋转 =====
void Transform::SetRotation(const glm::vec3& rotation) {
    m_Rotation = rotation;
    UpdateVectors();
}

void Transform::SetRotation(float pitch, float yaw, float roll) {
    m_Rotation = glm::vec3(pitch, yaw, roll);
    UpdateVectors();
}

void Transform::Rotate(const glm::vec3& delta) {
    m_Rotation += delta;
    UpdateVectors();
}

void Transform::Rotate(float pitch, float yaw, float roll) {
    m_Rotation += glm::vec3(pitch, yaw, roll);
    UpdateVectors();
}

// ===== 缩放 =====
void Transform::SetScale(const glm::vec3& scale) {
    m_Scale = scale;
}

void Transform::SetScale(float uniform) {
    m_Scale = glm::vec3(uniform);
}

void Transform::SetScale(float x, float y, float z) {
    m_Scale = glm::vec3(x, y, z);
}

void Transform::Scale(const glm::vec3& delta) {
    m_Scale += delta;
}

void Transform::Scale(float factor) {
    m_Scale *= factor;
}

// ===== 获取变换矩阵 =====
glm::mat4 Transform::GetModelMatrix() const {
    glm::mat4 model = glm::mat4(1.0f);

    // 平移
    model = glm::translate(model, m_Position);

    // 旋转(按 Z, Y, X 顺序,避免万向锁)
    model = glm::rotate(model, glm::radians(m_Rotation.z), glm::vec3(0, 0, 1));
    model = glm::rotate(model, glm::radians(m_Rotation.y), glm::vec3(0, 1, 0));
    model = glm::rotate(model, glm::radians(m_Rotation.x), glm::vec3(1, 0, 0));

    // 缩放
    model = glm::scale(model, m_Scale);

    return model;
}

// ===== 更新方向向量 =====
void Transform::UpdateVectors() {
    // 将欧拉角转换为弧度
    float pitch = glm::radians(m_Rotation.x);
    float yaw = glm::radians(m_Rotation.y);
    float roll = glm::radians(m_Rotation.z);

    // 计算前向向量
    m_Forward.x = cos(yaw) * cos(pitch);
    m_Forward.y = sin(pitch);
    m_Forward.z = sin(yaw) * cos(pitch);
    m_Forward = glm::normalize(m_Forward);

    // 计算右向量
    m_Right.x = cos(yaw);
    m_Right.y = 0;
    m_Right.z = sin(yaw);
    m_Right = glm::normalize(m_Right);

    // 计算上向量(前向与右向的叉积)
    m_Up = glm::cross(m_Right, m_Forward);
    m_Up = glm::normalize(m_Up);
}

// ===== 重置为单位变换 =====
void Transform::Reset() {
    m_Position = glm::vec3(0.0f);
    m_Rotation = glm::vec3(0.0f);
    m_Scale = glm::vec3(1.0f);
    UpdateVectors();
}

//===========================================================
// 文件: Texture.cpp
// 路径: CandyRenderEngine/Texture.cpp
// 说明: 纹理管理实现文件
//===========================================================

#include "pch.h"
#include "Texture.h"

// 包含 stb_image 头文件(实现放在单独的文件中)
#include "stb_image.h"

Texture::Texture()
    : m_ID(0)
    , m_Width(0)
    , m_Height(0)
    , m_Type("diffuse")
{
}

Texture::Texture(const std::string& path)
    : m_ID(0)
    , m_Width(0)
    , m_Height(0)
    , m_Path(path)
    , m_Type("diffuse")
{
    LoadFromFile(path);
}

Texture::Texture(const std::string& path, const std::string& type)
    : m_ID(0)
    , m_Width(0)
    , m_Height(0)
    , m_Path(path)
    , m_Type(type)
{
    LoadFromFile(path);
}

Texture::~Texture()
{
    if (m_ID != 0)
    {
        glDeleteTextures(1, &m_ID);
    }
}

bool Texture::LoadFromFile(const std::string& path)
{
    if (m_ID != 0)
    {
        glDeleteTextures(1, &m_ID);
        m_ID = 0;
    }

    int width, height, channels;
    unsigned char* data = stbi_load(path.c_str(), &width, &height, &channels, 0);

    if (!data)
    {
        OutputDebugStringA(("Failed to load texture: " + path + "\n").c_str());
        return false;
    }

    m_Width = width;
    m_Height = height;

    glGenTextures(1, &m_ID);
    glBindTexture(GL_TEXTURE_2D, m_ID);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    GLenum format = GL_RGB;
    if (channels == 1)
        format = GL_RED;
    else if (channels == 3)
        format = GL_RGB;
    else if (channels == 4)
        format = GL_RGBA;

    glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);

    stbi_image_free(data);

    OutputDebugStringA(("Loaded texture: " + path + "\n").c_str());
    return true;
}

void Texture::Bind(unsigned int slot) const
{
    glActiveTexture(GL_TEXTURE0 + slot);
    glBindTexture(GL_TEXTURE_2D, m_ID);
}

void Texture::Unbind() const
{
    glBindTexture(GL_TEXTURE_2D, 0);
}

//===========================================================
// 文件: stb_image_impl.cpp
// 路径: CandyRenderEngine/stb_image_impl.cpp
// 说明: STB 图像库实现(只编译一次)
//===========================================================

#include "pch.h"

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

//===========================================================
// 文件: Shader.cpp
// 路径: CandyRenderEngine/Core/Shader.cpp
//===========================================================

#include "pch.h"
#include "Shader.h"
#include <fstream>
#include <sstream>

Shader::Shader() : m_ID(0) {}

Shader::~Shader() {
    if (m_ID != 0) {
        glDeleteProgram(m_ID);
    }
}

bool Shader::LoadFromFile(const std::string& vertexPath, const std::string& fragmentPath) {
    std::string vertexSource = ReadFile(vertexPath);
    std::string fragmentSource = ReadFile(fragmentPath);

    if (vertexSource.empty() || fragmentSource.empty()) {
        return false;
    }

    return LoadFromSource(vertexSource, fragmentSource);
}

bool Shader::LoadFromSource(const std::string& vertexSource, const std::string& fragmentSource) {
    if (m_ID != 0) {
        glDeleteProgram(m_ID);
        m_ID = 0;
        m_UniformLocationCache.clear();
    }

    GLuint vertexShader = CompileShader(GL_VERTEX_SHADER, vertexSource);
    if (vertexShader == 0) return false;

    GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, fragmentSource);
    if (fragmentShader == 0) {
        glDeleteShader(vertexShader);
        return false;
    }

    bool success = LinkProgram(vertexShader, fragmentShader);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    return success;
}

GLuint Shader::CompileShader(GLenum type, const std::string& source) {
    GLuint shader = glCreateShader(type);
    const char* src = source.c_str();
    glShaderSource(shader, 1, &src, nullptr);
    glCompileShader(shader);

    if (!CheckCompileErrors(shader, type == GL_VERTEX_SHADER ? "VERTEX" : "FRAGMENT")) {
        glDeleteShader(shader);
        return 0;
    }

    return shader;
}

bool Shader::LinkProgram(GLuint vertexShader, GLuint fragmentShader) {
    m_ID = glCreateProgram();
    glAttachShader(m_ID, vertexShader);
    glAttachShader(m_ID, fragmentShader);
    glLinkProgram(m_ID);

    if (!CheckLinkErrors(m_ID)) {
        glDeleteProgram(m_ID);
        m_ID = 0;
        return false;
    }

    return true;
}

void Shader::Use() const {
    if (m_ID != 0) {
        glUseProgram(m_ID);
    }
}

void Shader::Unuse() const {
    glUseProgram(0);
}

void Shader::SetBool(const std::string& name, bool value) const {
    SetInt(name, (int)value);
}

void Shader::SetInt(const std::string& name, int value) const {
    GLint location = GetUniformLocation(name);
    if (location != -1) glUniform1i(location, value);
}

void Shader::SetFloat(const std::string& name, float value) const {
    GLint location = GetUniformLocation(name);
    if (location != -1) glUniform1f(location, value);
}

void Shader::SetVec2(const std::string& name, const glm::vec2& value) const {
    GLint location = GetUniformLocation(name);
    if (location != -1) glUniform2fv(location, 1, glm::value_ptr(value));
}

void Shader::SetVec3(const std::string& name, const glm::vec3& value) const {
    GLint location = GetUniformLocation(name);
    if (location != -1) glUniform3fv(location, 1, glm::value_ptr(value));
}

void Shader::SetVec4(const std::string& name, const glm::vec4& value) const {
    GLint location = GetUniformLocation(name);
    if (location != -1) glUniform4fv(location, 1, glm::value_ptr(value));
}

void Shader::SetMat2(const std::string& name, const glm::mat2& mat) const {
    GLint location = GetUniformLocation(name);
    if (location != -1) glUniformMatrix2fv(location, 1, GL_FALSE, glm::value_ptr(mat));
}

void Shader::SetMat3(const std::string& name, const glm::mat3& mat) const {
    GLint location = GetUniformLocation(name);
    if (location != -1) glUniformMatrix3fv(location, 1, GL_FALSE, glm::value_ptr(mat));
}

void Shader::SetMat4(const std::string& name, const glm::mat4& mat) const {
    GLint location = GetUniformLocation(name);
    if (location != -1) glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(mat));
}

GLint Shader::GetUniformLocation(const std::string& name) const {
    if (m_UniformLocationCache.find(name) != m_UniformLocationCache.end()) {
        return m_UniformLocationCache[name];
    }

    GLint location = glGetUniformLocation(m_ID, name.c_str());
    m_UniformLocationCache[name] = location;

    if (location == -1) {
        OutputDebugStringA(("Warning: Uniform '" + name + "' not found\n").c_str());
    }

    return location;
}

bool Shader::CheckCompileErrors(GLuint shader, const std::string& type) {
    GLint success;
    GLchar infoLog[1024];

    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(shader, 1024, NULL, infoLog);
        std::string msg = "Shader Compile Error (" + type + "):\n" + std::string(infoLog);
        OutputDebugStringA(msg.c_str());
        return false;
    }
    return true;
}

bool Shader::CheckLinkErrors(GLuint program) {
    GLint success;
    GLchar infoLog[1024];

    glGetProgramiv(program, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(program, 1024, NULL, infoLog);
        std::string msg = "Program Link Error:\n" + std::string(infoLog);
        OutputDebugStringA(msg.c_str());
        return false;
    }
    return true;
}

std::string Shader::ReadFile(const std::string& filePath) {
    std::ifstream file(filePath);
    if (!file.is_open()) {
        OutputDebugStringA(("Failed to open file: " + filePath + "\n").c_str());
        return "";
    }

    std::stringstream buffer;
    buffer << file.rdbuf();
    return buffer.str();
}

//===========================================================
// 文件: Scene.cpp
// 路径: CandyRenderEngine/Scene.cpp
// 说明: 场景管理实现文件
//===========================================================

#include "pch.h"
#include "Scene.h"
#include "Model.h"
#include "Shader.h"
#include "Light.h"
#include "Camera.h"

Scene::Scene()
    : m_Name("DefaultScene")
    , m_CurrentTime(0.0f) {
}

Scene::Scene(const std::string& name)
    : m_Name(name)
    , m_CurrentTime(0.0f) {
}

Scene::~Scene() {
    Clear();
}

void Scene::AddModel(std::shared_ptr<Model> model) {
    if (model) {
        m_Models.push_back(model);
    }
}

void Scene::RemoveModel(Model* model) {
    auto it = std::find_if(m_Models.begin(), m_Models.end(),
        [model](const std::shared_ptr<Model>& ptr) { return ptr.get() == model; });
    if (it != m_Models.end()) {
        m_Models.erase(it);
    }
}

void Scene::RemoveModel(size_t index) {
    if (index < m_Models.size()) {
        m_Models.erase(m_Models.begin() + index);
    }
}

void Scene::ClearModels() {
    m_Models.clear();
}

Model* Scene::GetModel(size_t index) const {
    if (index < m_Models.size()) {
        return m_Models[index].get();
    }
    return nullptr;
}

Model* Scene::FindModelByName(const std::string& name) const {
    for (const auto& model : m_Models) {
        if (model && model->GetName() == name) {
            return model.get();
        }
    }
    return nullptr;
}

void Scene::AddLight(std::shared_ptr<Light> light) {
    if (light) {
        m_Lights.push_back(light);
    }
}

void Scene::RemoveLight(Light* light) {
    auto it = std::find_if(m_Lights.begin(), m_Lights.end(),
        [light](const std::shared_ptr<Light>& ptr) { return ptr.get() == light; });
    if (it != m_Lights.end()) {
        m_Lights.erase(it);
    }
}

void Scene::ClearLights() {
    m_Lights.clear();
}

Light* Scene::GetLight(size_t index) const {
    if (index < m_Lights.size()) {
        return m_Lights[index].get();
    }
    return nullptr;
}

void Scene::SetMainCamera(std::shared_ptr<Camera> camera) {
    m_MainCamera = camera;
}

void Scene::Render(Shader& shader) const {
    if (!m_MainCamera) return;

    glm::mat4 view = m_MainCamera->GetViewMatrix();
    glm::vec3 cameraPos = m_MainCamera->GetPosition();

    shader.SetMat4("u_View", view);
    shader.SetVec3("u_ViewPos", cameraPos);

    shader.SetVec3("u_LightPos", glm::vec3(2.0f, 5.0f, 3.0f));
    shader.SetVec3("u_LightColor", glm::vec3(1.0f, 1.0f, 1.0f));

    for (const auto& model : m_Models) {
        if (model) {
            model->Draw(shader);
        }
    }
}

void Scene::Update(float deltaTime) {
    m_CurrentTime += deltaTime;
}

void Scene::Clear() {
    m_Models.clear();
    m_Lights.clear();
    m_MainCamera = nullptr;
    m_CurrentTime = 0.0f;
}

//===========================================================
// 文件: Renderer.cpp
// 路径: CandyRenderEngine/Renderer.cpp
// 说明: 主渲染器实现
//===========================================================

#include "pch.h"
#include "Renderer.h"
#include "Camera.h"
#include "Transform.h"
#include <glad/glad.h>
#include <vector>

#pragma comment(lib, "opengl32.lib")

// 顶点着色器
static const char* vertexShaderSource = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 ourColor;
uniform mat4 u_Model;
uniform mat4 u_View;
uniform mat4 u_Projection;
void main() {
    gl_Position = u_Projection * u_View * u_Model * vec4(aPos, 1.0);
    ourColor = aColor;
}
)";

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

// 网格顶点着色器
static const char* gridVertexSource = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 u_View;
uniform mat4 u_Projection;
void main() {
    gl_Position = u_Projection * u_View * vec4(aPos, 1.0);
}
)";

// 网格片段着色器
static const char* gridFragmentSource = R"(
#version 330 core
out vec4 FragColor;
void main() {
    FragColor = vec4(0.3, 0.3, 0.4, 1.0);
}
)";

static GLuint CompileShader(GLenum type, const char* source) {
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &source, nullptr);
    glCompileShader(shader);

    GLint success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        char infoLog[512];
        glGetShaderInfoLog(shader, 512, nullptr, infoLog);
        OutputDebugStringA(("Shader compile error: " + std::string(infoLog) + "\n").c_str());
        glDeleteShader(shader);
        return 0;
    }
    return shader;
}

static GLuint LinkProgram(GLuint vs, GLuint fs) {
    GLuint program = glCreateProgram();
    glAttachShader(program, vs);
    glAttachShader(program, fs);
    glLinkProgram(program);

    GLint success;
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    if (!success) {
        char infoLog[512];
        glGetProgramInfoLog(program, 512, nullptr, infoLog);
        OutputDebugStringA(("Program link error: " + std::string(infoLog) + "\n").c_str());
        glDeleteProgram(program);
        return 0;
    }
    return program;
}

Renderer::Renderer()
    : hwnd(nullptr)
    , hdc(nullptr)
    , hglrc(nullptr)
    , initialized(false)
    , shaderProgram(0)
    , gridProgram(0)
    , VAO(0)
    , VBO(0)
    , EBO(0)
    , gridVAO(0)
    , gridVBO(0)
    , m_Camera(nullptr)
    , m_ModelTransform(nullptr)
    , m_WireframeMode(false)
    , m_ShowGrid(true) {
}

Renderer::~Renderer() {
    Shutdown();
}

bool Renderer::Initialize(HWND parentHwnd, int width, int height) {
    OutputDebugStringA("=== Renderer Initialize START ===\n");

    hwnd = parentHwnd;
    hdc = GetDC(hwnd);
    if (!hdc) {
        OutputDebugStringA("GetDC failed\n");
        return false;
    }

    PIXELFORMATDESCRIPTOR pfd = {
        sizeof(PIXELFORMATDESCRIPTOR), 1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA, 32,
        0,0,0,0,0,0,0,0,0,0,0,0,0,
        24,8,0,PFD_MAIN_PLANE,0,0,0,0
    };

    int pixelFormat = ChoosePixelFormat(hdc, &pfd);
    if (!pixelFormat) {
        OutputDebugStringA("ChoosePixelFormat failed\n");
        return false;
    }
    if (!SetPixelFormat(hdc, pixelFormat, &pfd)) {
        OutputDebugStringA("SetPixelFormat failed\n");
        return false;
    }

    hglrc = wglCreateContext(hdc);
    if (!hglrc) {
        OutputDebugStringA("wglCreateContext failed\n");
        return false;
    }
    if (!wglMakeCurrent(hdc, hglrc)) {
        OutputDebugStringA("wglMakeCurrent failed\n");
        return false;
    }

    if (!gladLoadGL()) {
        OutputDebugStringA("gladLoadGL failed\n");
        return false;
    }

    const char* version = (const char*)glGetString(GL_VERSION);
    OutputDebugStringA(("OpenGL Version: " + std::string(version) + "\n").c_str());

    // 编译着色器
    GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShaderSource);
    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
    shaderProgram = LinkProgram(vs, fs);
    glDeleteShader(vs);
    glDeleteShader(fs);

    vs = CompileShader(GL_VERTEX_SHADER, gridVertexSource);
    fs = CompileShader(GL_FRAGMENT_SHADER, gridFragmentSource);
    gridProgram = LinkProgram(vs, fs);
    glDeleteShader(vs);
    glDeleteShader(fs);

    CreateCube();
    CreateGrid();

    // 创建相机和变换对象
    m_Camera = new Camera();
    m_ModelTransform = new Transform();

    m_Camera->SetPosition(glm::vec3(3.0f, 3.0f, 5.0f));
    m_Camera->SetTarget(glm::vec3(0.0f));
    m_Camera->EnableOrbitMode(true);
    m_Camera->SetZoom(45.0f);

    m_ModelTransform->SetScale(1.0f);
    m_ModelTransform->SetRotation(45.0f, 45.0f, 0.0f);

    glViewport(0, 0, width, height);
    glEnable(GL_DEPTH_TEST);

    initialized = true;
    OutputDebugStringA("=== Renderer Initialize SUCCESS ===\n");
    return true;
}

void Renderer::CreateCube() {
    float vertices[] = {
        -0.5f, -0.5f,  0.5f,  1.0f, 0.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  0.0f, 1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  0.0f, 0.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 1.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  1.0f, 0.5f, 0.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f, 0.5f,
         0.5f,  0.5f, -0.5f,  0.5f, 0.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f, 0.5f,
    };

    unsigned int indices[] = {
        0,1,2, 2,3,0, 1,5,6, 6,2,1,
        5,4,7, 7,6,5, 4,0,3, 3,7,4,
        3,2,6, 6,7,3, 4,5,1, 1,0,4
    };

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, 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);

    glBindVertexArray(0);
}

void Renderer::CreateGrid() {
    std::vector<float> vertices;
    int gridSize = 20;
    float step = 0.5f;
    float start = -gridSize * step / 2;

    for (int i = 0; i <= gridSize; i++) {
        float pos = start + i * step;
        vertices.push_back(pos); vertices.push_back(0.0f); vertices.push_back(start);
        vertices.push_back(pos); vertices.push_back(0.0f); vertices.push_back(-start);
        vertices.push_back(start); vertices.push_back(0.0f); vertices.push_back(pos);
        vertices.push_back(-start); vertices.push_back(0.0f); vertices.push_back(pos);
    }

    glGenVertexArrays(1, &gridVAO);
    glGenBuffers(1, &gridVBO);

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

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

    glBindVertexArray(0);
}

void Renderer::RenderFrame() {
    if (!initialized || !m_Camera || !m_ModelTransform) return;

    glClearColor(0.15f, 0.15f, 0.2f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    RECT rect;
    GetClientRect(hwnd, &rect);
    int width = rect.right - rect.left;
    int height = rect.bottom - rect.top;
    if (width == 0) width = 1;
    if (height == 0) height = 1;

    float aspect = (float)width / (float)height;
    glm::mat4 projection = m_Camera->GetProjectionMatrix(aspect);
    glm::mat4 view = m_Camera->GetViewMatrix();
    glm::mat4 model = m_ModelTransform->GetModelMatrix();

    // 绘制网格
    if (m_ShowGrid) {
        glUseProgram(gridProgram);
        glUniformMatrix4fv(glGetUniformLocation(gridProgram, "u_View"), 1, GL_FALSE, glm::value_ptr(view));
        glUniformMatrix4fv(glGetUniformLocation(gridProgram, "u_Projection"), 1, GL_FALSE, glm::value_ptr(projection));

        glBindVertexArray(gridVAO);
        // 修复:计算正确的顶点数量
        // 网格线数量 = (gridSize+1) * 4 条线,每条线2个顶点
        int gridSize = 20;
        int vertexCount = (gridSize + 1) * 4 * 2;
        glDrawArrays(GL_LINES, 0, vertexCount);
        glBindVertexArray(0);
    }

    // 绘制立方体
    glUseProgram(shaderProgram);
    glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "u_Model"), 1, GL_FALSE, glm::value_ptr(model));
    glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "u_View"), 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "u_Projection"), 1, GL_FALSE, glm::value_ptr(projection));

    if (m_WireframeMode) {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    }

    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);

    if (m_WireframeMode) {
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }

    SwapBuffers(hdc);
}

void Renderer::ProcessMouseMovement(float xOffset, float yOffset) {
    if (m_Camera) m_Camera->ProcessMouseMovement(xOffset, yOffset);
}

void Renderer::ProcessMouseScroll(float yOffset) {
    if (m_Camera) m_Camera->ProcessMouseScroll(yOffset);
}

void Renderer::ProcessPan(float xOffset, float yOffset) {
    if (m_Camera) m_Camera->ProcessPan(xOffset, yOffset);
}

void Renderer::ResetCamera() {
    if (m_Camera) m_Camera->Reset();
}

void Renderer::FitView() {
    if (m_Camera) {
        m_Camera->SetTarget(glm::vec3(0.0f));
        m_Camera->SetPosition(glm::vec3(3.0f, 3.0f, 5.0f));
        m_Camera->SetZoom(45.0f);
    }
}

void Renderer::SetModelRotation(float x, float y, float z) {
    if (m_ModelTransform) m_ModelTransform->SetRotation(x, y, z);
}

void Renderer::SetModelScale(float scale) {
    if (m_ModelTransform) m_ModelTransform->SetScale(scale);
}

void Renderer::SetModelPosition(float x, float y, float z) {
    if (m_ModelTransform) m_ModelTransform->SetPosition(x, y, z);
}

void Renderer::SetWireframeMode(bool enabled) {
    m_WireframeMode = enabled;
}

void Renderer::ShowGrid(bool show) {
    m_ShowGrid = show;
}

void Renderer::GetCameraPosition(float& x, float& y, float& z) {
    if (m_Camera) {
        glm::vec3 pos = m_Camera->GetPosition();
        x = pos.x;
        y = pos.y;
        z = pos.z;
    }
    else {
        x = y = z = 0;
    }
}

void Renderer::Resize(int width, int height) {
    if (initialized) {
        glViewport(0, 0, width, height);
    }
}

void Renderer::Shutdown() {
    if (initialized) {
        if (EBO) glDeleteBuffers(1, &EBO);
        if (VBO) glDeleteBuffers(1, &VBO);
        if (VAO) glDeleteVertexArrays(1, &VAO);
        if (gridVBO) glDeleteBuffers(1, &gridVBO);
        if (gridVAO) glDeleteVertexArrays(1, &gridVAO);
        if (shaderProgram) glDeleteProgram(shaderProgram);
        if (gridProgram) glDeleteProgram(gridProgram);

        delete m_Camera;
        delete m_ModelTransform;
        m_Camera = nullptr;
        m_ModelTransform = nullptr;

        if (hglrc) {
            wglMakeCurrent(nullptr, nullptr);
            wglDeleteContext(hglrc);
            hglrc = nullptr;
        }
        if (hdc && hwnd) {
            ReleaseDC(hwnd, hdc);
            hdc = nullptr;
        }
        hwnd = nullptr;
        initialized = false;
    }
}

//===========================================================
// 文件: pch.cpp
// 路径: CandyRenderEngine/pch.cpp
// 说明: 预编译头对应的源文件,用于生成预编译头文件 (.pch)
// 依赖: pch.h
//===========================================================

#include "pch.h"

//===========================================================
// 文件: Model.cpp
// 路径: CandyRenderEngine/Model.cpp
// 说明: 模型管理实现文件
//===========================================================

#include "pch.h"
#include "Model.h"
#include "Shader.h"
#include <cmath>
#include <limits>

#ifndef FLT_MAX
#define FLT_MAX 3.402823466e+38F
#endif

Model::Model()
    : m_Name("Empty")
    , m_Visible(true)
    , m_MinBounds(0.0f)
    , m_MaxBounds(0.0f) {
}

Model::Model(const std::string& path)
    : m_Name(path)
    , m_Visible(true)
    , m_MinBounds(0.0f)
    , m_MaxBounds(0.0f) {
    LoadModel(path);
}

Model::~Model() {
    ClearMeshes();
}

bool Model::LoadModel(const std::string& path) {
    OutputDebugStringA(("Loading model: " + path + "\n").c_str());
    return true;
}

void Model::Draw(Shader& shader) const {
    if (!m_Visible) return;

    shader.SetMat4("u_Model", m_Transform.GetModelMatrix());

    for (const auto& mesh : m_Meshes) {
        if (mesh) {
            mesh->Draw(shader);
        }
    }
}

void Model::AddMesh(std::shared_ptr<Mesh> mesh) {
    if (mesh) {
        m_Meshes.push_back(mesh);
        CalculateBoundingBox();
    }
}

void Model::ClearMeshes() {
    m_Meshes.clear();
}

Mesh* Model::GetMesh(size_t index) const {
    if (index < m_Meshes.size()) {
        return m_Meshes[index].get();
    }
    return nullptr;
}

void Model::SetPosition(const glm::vec3& position) {
    m_Transform.SetPosition(position);
}

void Model::SetRotation(const glm::vec3& rotation) {
    m_Transform.SetRotation(rotation);
}

void Model::SetScale(const glm::vec3& scale) {
    m_Transform.SetScale(scale);
}

void Model::CalculateBoundingBox() {
    if (m_Meshes.empty()) {
        m_MinBounds = glm::vec3(0.0f);
        m_MaxBounds = glm::vec3(0.0f);
        return;
    }

    glm::vec3 minBounds(FLT_MAX);
    glm::vec3 maxBounds(-FLT_MAX);

    for (const auto& mesh : m_Meshes) {
        if (!mesh) continue;

        for (const auto& vertex : mesh->GetVertices()) {
            glm::vec3 worldPos = m_Transform.GetModelMatrix() * glm::vec4(vertex.Position, 1.0f);

            minBounds.x = (std::min)(minBounds.x, worldPos.x);
            minBounds.y = (std::min)(minBounds.y, worldPos.y);
            minBounds.z = (std::min)(minBounds.z, worldPos.z);

            maxBounds.x = (std::max)(maxBounds.x, worldPos.x);
            maxBounds.y = (std::max)(maxBounds.y, worldPos.y);
            maxBounds.z = (std::max)(maxBounds.z, worldPos.z);
        }
    }

    m_MinBounds = minBounds;
    m_MaxBounds = maxBounds;
}

float Model::GetRadius() const {
    glm::vec3 center = GetCenter();
    float maxDist = 0.0f;

    glm::vec3 corners[8] = {
        m_MinBounds,
        glm::vec3(m_MaxBounds.x, m_MinBounds.y, m_MinBounds.z),
        glm::vec3(m_MinBounds.x, m_MaxBounds.y, m_MinBounds.z),
        glm::vec3(m_MaxBounds.x, m_MaxBounds.y, m_MinBounds.z),
        glm::vec3(m_MinBounds.x, m_MinBounds.y, m_MaxBounds.z),
        glm::vec3(m_MaxBounds.x, m_MinBounds.y, m_MaxBounds.z),
        glm::vec3(m_MinBounds.x, m_MaxBounds.y, m_MaxBounds.z),
        m_MaxBounds
    };

    for (const auto& corner : corners) {
        float dist = glm::distance(center, corner);
        maxDist = (std::max)(maxDist, dist);
    }

    return maxDist;
}

//===========================================================
// 文件: Mesh.cpp
// 路径: CandyRenderEngine/Mesh.cpp
// 说明: 网格数据管理实现文件
//===========================================================

#include "pch.h"
#include "Mesh.h"
#include "Shader.h"

Mesh::Mesh()
    : m_VAO(0), m_VBO(0), m_EBO(0), m_IsInitialized(false) {
}

Mesh::Mesh(const std::vector<Vertex>& vertices, const std::vector<unsigned int>& indices)
    : m_Vertices(vertices)
    , m_Indices(indices)
    , m_VAO(0), m_VBO(0), m_EBO(0)
    , m_IsInitialized(false) {
    SetupMesh();
}

Mesh::Mesh(const std::vector<Vertex>& vertices, const std::vector<unsigned int>& indices,
    const std::vector<std::shared_ptr<Texture>>& textures)
    : m_Vertices(vertices)
    , m_Indices(indices)
    , m_Textures(textures)
    , m_VAO(0), m_VBO(0), m_EBO(0)
    , m_IsInitialized(false) {
    SetupMesh();
}

Mesh::~Mesh() {
    Clear();
}

void Mesh::SetupMesh() {
    glGenVertexArrays(1, &m_VAO);
    glGenBuffers(1, &m_VBO);
    glGenBuffers(1, &m_EBO);

    glBindVertexArray(m_VAO);

    glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
    glBufferData(GL_ARRAY_BUFFER, m_Vertices.size() * sizeof(Vertex), m_Vertices.data(), GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_Indices.size() * sizeof(unsigned int), m_Indices.data(), GL_STATIC_DRAW);

    // 位置
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Position));
    glEnableVertexAttribArray(0);

    // 法线
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
    glEnableVertexAttribArray(1);

    // 纹理坐标
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
    glEnableVertexAttribArray(2);

    // 切线
    glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Tangent));
    glEnableVertexAttribArray(3);

    // 副切线
    glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Bitangent));
    glEnableVertexAttribArray(4);

    glBindVertexArray(0);

    m_IsInitialized = true;
}

void Mesh::Draw(Shader& shader) const {
    if (!m_IsInitialized || m_Vertices.empty()) return;

    unsigned int diffuseIdx = 0;
    unsigned int specularIdx = 0;
    unsigned int normalIdx = 0;
    unsigned int heightIdx = 0;

    for (size_t i = 0; i < m_Textures.size(); ++i) {
        if (m_Textures[i]) {
            m_Textures[i]->Bind((unsigned int)i);

            std::string name = m_Textures[i]->GetType();
            std::string uniformName;

            if (name == "diffuse") {
                uniformName = "material.diffuse" + std::to_string(diffuseIdx++);
            }
            else if (name == "specular") {
                uniformName = "material.specular" + std::to_string(specularIdx++);
            }
            else if (name == "normal") {
                uniformName = "material.normal" + std::to_string(normalIdx++);
            }
            else if (name == "height") {
                uniformName = "material.height" + std::to_string(heightIdx++);
            }
            else {
                uniformName = "material." + name;
            }

            shader.SetInt(uniformName, (int)i);
        }
    }

    glBindVertexArray(m_VAO);
    glDrawElements(GL_TRIANGLES, (GLsizei)m_Indices.size(), GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);

    glActiveTexture(GL_TEXTURE0);
}

void Mesh::SetVertices(const std::vector<Vertex>& vertices) {
    m_Vertices = vertices;
    if (m_IsInitialized) {
        SetupMesh();
    }
}

void Mesh::SetIndices(const std::vector<unsigned int>& indices) {
    m_Indices = indices;
    if (m_IsInitialized) {
        SetupMesh();
    }
}

void Mesh::SetTextures(const std::vector<std::shared_ptr<Texture>>& textures) {
    m_Textures = textures;
}

void Mesh::Clear() {
    if (m_IsInitialized) {
        if (m_VAO != 0) {
            glDeleteVertexArrays(1, &m_VAO);
            m_VAO = 0;
        }
        if (m_VBO != 0) {
            glDeleteBuffers(1, &m_VBO);
            m_VBO = 0;
        }
        if (m_EBO != 0) {
            glDeleteBuffers(1, &m_EBO);
            m_EBO = 0;
        }
        m_IsInitialized = false;
    }

    m_Vertices.clear();
    m_Indices.clear();
    m_Textures.clear();
}

//===========================================================
// 文件: Material.cpp
// 路径: CandyRenderEngine/Material.cpp
// 说明: 材质系统实现文件
//===========================================================

#include "pch.h"
#include "Material.h"
#include "Shader.h"
#include "Texture.h"

Material::Material()
    : m_Name("DefaultMaterial") {
}

Material::Material(const MaterialProperties& properties)
    : m_Properties(properties)
    , m_Name("CustomMaterial") {
}

Material::~Material() {
    ClearTextures();
}

void Material::SetProperties(const MaterialProperties& properties) {
    m_Properties = properties;
}

void Material::SetTexture(const std::string& type, std::shared_ptr<Texture> texture) {
    if (texture) {
        m_Textures[type] = texture;
    }
}

std::shared_ptr<Texture> Material::GetTexture(const std::string& type) const {
    auto it = m_Textures.find(type);
    if (it != m_Textures.end()) {
        return it->second;
    }
    return nullptr;
}

void Material::ClearTextures() {
    m_Textures.clear();
}

void Material::Apply(Shader& shader) const {
    // 应用材质属性
    shader.SetVec3("material.ambient", m_Properties.Ambient);
    shader.SetVec3("material.diffuse", m_Properties.Diffuse);
    shader.SetVec3("material.specular", m_Properties.Specular);
    shader.SetFloat("material.shininess", m_Properties.Shininess);
    shader.SetFloat("material.opacity", m_Properties.Opacity);
    shader.SetFloat("material.metallic", m_Properties.Metallic);
    shader.SetFloat("material.roughness", m_Properties.Roughness);

    // 应用纹理
    int textureSlot = 0;
    for (const auto& pair : m_Textures) {
        if (pair.second) {
            pair.second->Bind(textureSlot);
            shader.SetInt(("material." + pair.first).c_str(), textureSlot);
            textureSlot++;
        }
    }
}

//===========================================================
// 文件: Light.cpp
// 路径: CandyRenderEngine/Light.cpp
// 说明: 光源管理实现文件
//===========================================================

#include "pch.h"
#include "Light.h"

Light::Light()
    : m_Type(LightType::Point)
    , m_Position(0.0f, 5.0f, 5.0f)
    , m_Direction(0.0f, -1.0f, 0.0f)
    , m_Color(1.0f, 1.0f, 1.0f)
    , m_Intensity(1.0f)
    , m_Range(10.0f)
    , m_ConstantAttenuation(1.0f)
    , m_LinearAttenuation(0.09f)
    , m_QuadraticAttenuation(0.032f)
    , m_InnerAngle(35.0f)
    , m_OuterAngle(45.0f)
    , m_Enabled(true) {
}

Light::Light(LightType type)
    : m_Type(type)
    , m_Position(0.0f, 5.0f, 5.0f)
    , m_Direction(0.0f, -1.0f, 0.0f)
    , m_Color(1.0f, 1.0f, 1.0f)
    , m_Intensity(1.0f)
    , m_Range(10.0f)
    , m_ConstantAttenuation(1.0f)
    , m_LinearAttenuation(0.09f)
    , m_QuadraticAttenuation(0.032f)
    , m_InnerAngle(35.0f)
    , m_OuterAngle(45.0f)
    , m_Enabled(true) {

    // 根据类型设置默认方向
    if (type == LightType::Directional) {
        m_Direction = glm::vec3(0.0f, -1.0f, 0.0f);
    }
}

void Light::SetAttenuation(float constant, float linear, float quadratic) {
    m_ConstantAttenuation = constant;
    m_LinearAttenuation = linear;
    m_QuadraticAttenuation = quadratic;
}

void Light::GetAttenuation(float& constant, float& linear, float& quadratic) const {
    constant = m_ConstantAttenuation;
    linear = m_LinearAttenuation;
    quadratic = m_QuadraticAttenuation;
}

void Light::SetSpotAngle(float innerAngle, float outerAngle) {
    m_InnerAngle = innerAngle;
    m_OuterAngle = outerAngle;
}

//===========================================================
// 文件: Frustum.cpp
// 路径: CandyRenderEngine/Frustum.cpp
// 说明: 视锥体实现文件
//===========================================================

#include "pch.h"
#include "Frustum.h"
#include <cmath>

Frustum::Frustum() {
    for (int i = 0; i < 6; ++i) {
        m_Planes[i] = glm::vec4(0.0f);
    }
}

void Frustum::Update(const glm::mat4& viewProjection) {
    // 提取视锥体平面
    // 左平面
    m_Planes[0].x = viewProjection[0][3] + viewProjection[0][0];
    m_Planes[0].y = viewProjection[1][3] + viewProjection[1][0];
    m_Planes[0].z = viewProjection[2][3] + viewProjection[2][0];
    m_Planes[0].w = viewProjection[3][3] + viewProjection[3][0];

    // 右平面
    m_Planes[1].x = viewProjection[0][3] - viewProjection[0][0];
    m_Planes[1].y = viewProjection[1][3] - viewProjection[1][0];
    m_Planes[1].z = viewProjection[2][3] - viewProjection[2][0];
    m_Planes[1].w = viewProjection[3][3] - viewProjection[3][0];

    // 下平面
    m_Planes[2].x = viewProjection[0][3] + viewProjection[0][1];
    m_Planes[2].y = viewProjection[1][3] + viewProjection[1][1];
    m_Planes[2].z = viewProjection[2][3] + viewProjection[2][1];
    m_Planes[2].w = viewProjection[3][3] + viewProjection[3][1];

    // 上平面
    m_Planes[3].x = viewProjection[0][3] - viewProjection[0][1];
    m_Planes[3].y = viewProjection[1][3] - viewProjection[1][1];
    m_Planes[3].z = viewProjection[2][3] - viewProjection[2][1];
    m_Planes[3].w = viewProjection[3][3] - viewProjection[3][1];

    // 近平面
    m_Planes[4].x = viewProjection[0][3] + viewProjection[0][2];
    m_Planes[4].y = viewProjection[1][3] + viewProjection[1][2];
    m_Planes[4].z = viewProjection[2][3] + viewProjection[2][2];
    m_Planes[4].w = viewProjection[3][3] + viewProjection[3][2];

    // 远平面
    m_Planes[5].x = viewProjection[0][3] - viewProjection[0][2];
    m_Planes[5].y = viewProjection[1][3] - viewProjection[1][2];
    m_Planes[5].z = viewProjection[2][3] - viewProjection[2][2];
    m_Planes[5].w = viewProjection[3][3] - viewProjection[3][2];

    // 归一化所有平面
    for (int i = 0; i < 6; ++i) {
        float length = sqrt(m_Planes[i].x * m_Planes[i].x +
            m_Planes[i].y * m_Planes[i].y +
            m_Planes[i].z * m_Planes[i].z);
        if (length > 0.0f) {
            m_Planes[i] /= length;
        }
    }
}

bool Frustum::IsBoxVisible(const BoundingBox& box) const {
    if (!box.IsValid()) return true;

    glm::vec3 corners[8];
    box.GetCorners(corners);

    for (int i = 0; i < 6; ++i) {
        const glm::vec4& plane = m_Planes[i];
        bool allOutside = true;

        for (int j = 0; j < 8; ++j) {
            float distance = plane.x * corners[j].x + plane.y * corners[j].y +
                plane.z * corners[j].z + plane.w;
            if (distance >= 0) {
                allOutside = false;
                break;
            }
        }

        if (allOutside) return false;
    }

    return true;
}

bool Frustum::IsSphereVisible(const glm::vec3& center, float radius) const {
    for (int i = 0; i < 6; ++i) {
        const glm::vec4& plane = m_Planes[i];
        float distance = plane.x * center.x + plane.y * center.y +
            plane.z * center.z + plane.w;
        if (distance < -radius) {
            return false;
        }
    }
    return true;
}

bool Frustum::IsPointVisible(const glm::vec3& point) const {
    for (int i = 0; i < 6; ++i) {
        const glm::vec4& plane = m_Planes[i];
        float distance = plane.x * point.x + plane.y * point.y +
            plane.z * point.z + plane.w;
        if (distance < 0) {
            return false;
        }
    }
    return true;
}

//===========================================================
// 文件: Export.cpp
// 路径: CandyRenderEngine/Export.cpp
// 说明: DLL 导出函数实现
//===========================================================

#include "pch.h"
#include "Export.h"
#include "Renderer.h"

static Renderer g_Renderer;

bool Initialize(HWND hwnd, int width, int height) {
    return g_Renderer.Initialize(hwnd, width, height);
}

void Shutdown() {
    g_Renderer.Shutdown();
}

void RenderFrame() {
    g_Renderer.RenderFrame();
}

void Resize(int width, int height) {
    g_Renderer.Resize(width, height);
}

void ProcessMouseMovement(float xOffset, float yOffset) {
    g_Renderer.ProcessMouseMovement(xOffset, yOffset);
}

void ProcessMouseScroll(float yOffset) {
    g_Renderer.ProcessMouseScroll(yOffset);
}

void ProcessPan(float xOffset, float yOffset) {
    g_Renderer.ProcessPan(xOffset, yOffset);
}

void ResetCamera() {
    g_Renderer.ResetCamera();
}

void FitView() {
    g_Renderer.FitView();
}

void SetModelRotation(float x, float y, float z) {
    g_Renderer.SetModelRotation(x, y, z);
}

void SetModelScale(float scale) {
    g_Renderer.SetModelScale(scale);
}

void SetModelPosition(float x, float y, float z) {
    g_Renderer.SetModelPosition(x, y, z);
}

void SetWireframeMode(bool enabled) {
    g_Renderer.SetWireframeMode(enabled);
}

void ShowGrid(bool show) {
    g_Renderer.ShowGrid(show);
}

void GetCameraPosition(float* x, float* y, float* z) {
    g_Renderer.GetCameraPosition(*x, *y, *z);
}

bool GetWireframeMode() {
    return g_Renderer.GetWireframeMode();
}

bool IsGridVisible() {
    return g_Renderer.IsGridVisible();
}

//===========================================================
// 文件: dllmain.cpp
// 路径: CandyRenderEngine/dllmain.cpp
// 说明: DLL 入口点文件,处理 DLL 的加载/卸载事件
// 依赖: pch.h, windows.h
//===========================================================

#include "pch.h"

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        // DLL 被加载到进程地址空间时调用
        break;
    case DLL_THREAD_ATTACH:
        // 进程中创建新线程时调用
        break;
    case DLL_THREAD_DETACH:
        // 线程正常退出时调用
        break;
    case DLL_PROCESS_DETACH:
        // DLL 从进程地址空间卸载时调用
        break;
    }
    return TRUE;
}

//===========================================================
// 文件: Camera.cpp
// 路径: CandyRenderEngine/Core/Camera.cpp
// 说明: 相机系统实现文件,实现平移、旋转、缩放的具体逻辑
// 依赖: Camera.h, GLM 数学库
//===========================================================

#include "pch.h"
#include "Camera.h"
#include <cmath>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

Camera::Camera(glm::vec3 position, glm::vec3 up, float yaw, float pitch)
    : m_Position(position)
    , m_WorldUp(up)
    , m_Yaw(yaw)
    , m_Pitch(pitch)
    , m_Zoom(45.0f)
    , m_MoveSpeed(5.0f)
    , m_RotateSpeed(0.5f)
    , m_ZoomSpeed(2.0f)
    , m_Target(0.0f)
    , m_Radius(5.0f)
    , m_OrbitMode(false)
{
    for (int i = 0; i < 6; i++) m_Keys[i] = false;
    UpdateCameraVectors();
}

// ===== 获取视图矩阵 =====
glm::mat4 Camera::GetViewMatrix() const {
    if (m_OrbitMode) {
        // 轨道模式:相机围绕目标点旋转
        return glm::lookAt(m_Position, m_Target, m_Up);
    }
    return glm::lookAt(m_Position, m_Position + m_Front, m_Up);
}

// ===== 获取投影矩阵 =====
glm::mat4 Camera::GetProjectionMatrix(float aspectRatio) const {
    return glm::perspective(glm::radians(m_Zoom), aspectRatio, 0.1f, 1000.0f);
}

// ===== 键盘移动 =====
void Camera::ProcessKeyboard(CameraMovement direction, float deltaTime) {
    float velocity = m_MoveSpeed * deltaTime;

    if (m_OrbitMode) {
        // 轨道模式下,移动目标点
        switch (direction) {
        case CameraMovement::FORWARD:
            m_Target += m_Front * velocity;
            break;
        case CameraMovement::BACKWARD:
            m_Target -= m_Front * velocity;
            break;
        case CameraMovement::LEFT:
            m_Target -= m_Right * velocity;
            break;
        case CameraMovement::RIGHT:
            m_Target += m_Right * velocity;
            break;
        case CameraMovement::UP:
            m_Target += m_WorldUp * velocity;
            break;
        case CameraMovement::DOWN:
            m_Target -= m_WorldUp * velocity;
            break;
        }
        // 更新相机位置(保持距离)
        m_Position = m_Target - m_Front * m_Radius;
    }
    else {
        // 自由模式:移动相机位置
        switch (direction) {
        case CameraMovement::FORWARD:
            m_Position += m_Front * velocity;
            break;
        case CameraMovement::BACKWARD:
            m_Position -= m_Front * velocity;
            break;
        case CameraMovement::LEFT:
            m_Position -= m_Right * velocity;
            break;
        case CameraMovement::RIGHT:
            m_Position += m_Right * velocity;
            break;
        case CameraMovement::UP:
            m_Position += m_WorldUp * velocity;
            break;
        case CameraMovement::DOWN:
            m_Position -= m_WorldUp * velocity;
            break;
        }
    }
}

// ===== 鼠标旋转 =====
void Camera::ProcessMouseMovement(float xOffset, float yOffset, bool constrainPitch) {
    xOffset *= m_RotateSpeed;
    yOffset *= m_RotateSpeed;

    m_Yaw += xOffset;
    m_Pitch += yOffset;

    // 限制俯仰角,防止翻转
    if (constrainPitch) {
        if (m_Pitch > 89.0f) m_Pitch = 89.0f;
        if (m_Pitch < -89.0f) m_Pitch = -89.0f;
    }

    // 更新方向向量
    UpdateCameraVectors();

    // 轨道模式下,更新相机位置
    if (m_OrbitMode) {
        m_Position = m_Target - m_Front * m_Radius;
    }
}

// ===== 鼠标滚轮缩放 =====
void Camera::ProcessMouseScroll(float yOffset) {
    m_Zoom -= yOffset * m_ZoomSpeed;
    if (m_Zoom < 1.0f) m_Zoom = 1.0f;
    if (m_Zoom > 89.0f) m_Zoom = 89.0f;
}

// ===== 平移动画/平移 =====
void Camera::ProcessPan(float xOffset, float yOffset) {
    float panSpeed = 0.01f;
    glm::vec3 right = glm::normalize(glm::cross(m_Front, m_WorldUp));
    glm::vec3 up = glm::normalize(glm::cross(right, m_Front));

    if (m_OrbitMode) {
        m_Target += right * xOffset * panSpeed;
        m_Target += up * yOffset * panSpeed;
        m_Position = m_Target - m_Front * m_Radius;
    }
    else {
        m_Position += right * xOffset * panSpeed;
        m_Position += up * yOffset * panSpeed;
    }
}

// ===== 旋转视图(触摸/手势)=====
void Camera::ProcessRotate(float angleDelta) {
    // 简化实现,实际可根据需求扩展
    m_Yaw += angleDelta;
    UpdateCameraVectors();
    if (m_OrbitMode) {
        m_Position = m_Target - m_Front * m_Radius;
    }
}

// ===== 双指缩放 =====
void Camera::ProcessPinch(float zoomDelta) {
    float newZoom = m_Zoom - zoomDelta;
    if (newZoom < 1.0f) newZoom = 1.0f;
    if (newZoom > 89.0f) newZoom = 89.0f;
    m_Zoom = newZoom;
}

// ===== 轨道旋转 =====
void Camera::OrbitRotate(float xOffset, float yOffset) {
    if (!m_OrbitMode) return;

    m_Yaw += xOffset * m_RotateSpeed;
    m_Pitch += yOffset * m_RotateSpeed;

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

    UpdateCameraVectors();
    m_Position = m_Target - m_Front * m_Radius;
}

// ===== 轨道缩放 =====
void Camera::OrbitZoom(float zoomDelta) {
    if (!m_OrbitMode) return;

    m_Radius -= zoomDelta * m_ZoomSpeed;
    if (m_Radius < 0.5f) m_Radius = 0.5f;
    if (m_Radius > 100.0f) m_Radius = 100.0f;

    m_Position = m_Target - m_Front * m_Radius;
}

// ===== 轨道平移 =====
void Camera::OrbitPan(float xOffset, float yOffset) {
    if (!m_OrbitMode) return;

    float panSpeed = 0.01f;
    glm::vec3 right = glm::normalize(glm::cross(m_Front, m_WorldUp));
    glm::vec3 up = glm::normalize(glm::cross(right, m_Front));

    m_Target += right * xOffset * panSpeed;
    m_Target += up * yOffset * panSpeed;
    m_Position = m_Target - m_Front * m_Radius;
}

// ===== 设置目标点 =====
void Camera::SetTarget(const glm::vec3& target) {
    m_Target = target;
    if (m_OrbitMode) {
        m_Radius = glm::distance(m_Position, target);
        UpdateCameraVectors();
    }
}

// ===== 重置相机 =====
void Camera::Reset() {
    m_Position = glm::vec3(0.0f, 0.0f, 5.0f);
    m_Target = glm::vec3(0.0f);
    m_Radius = 5.0f;
    m_Yaw = -90.0f;
    m_Pitch = 0.0f;
    m_Zoom = 45.0f;
    UpdateCameraVectors();
    if (m_OrbitMode) {
        m_Position = m_Target - m_Front * m_Radius;
    }
}

// ===== 设置相机位置 =====
void Camera::SetPosition(const glm::vec3& position) {
    m_Position = position;
    if (m_OrbitMode) {
        m_Radius = glm::distance(position, m_Target);
        UpdateCameraVectors();
    }
}

// ===== 设置偏航角 =====
void Camera::SetYaw(float yaw) {
    m_Yaw = yaw;
    UpdateCameraVectors();
}

// ===== 设置俯仰角 =====
void Camera::SetPitch(float pitch) {
    m_Pitch = pitch;
    if (m_Pitch > 89.0f) m_Pitch = 89.0f;
    if (m_Pitch < -89.0f) m_Pitch = -89.0f;
    UpdateCameraVectors();
}

// ===== 设置缩放 =====
void Camera::SetZoom(float zoom) {
    m_Zoom = zoom;
    if (m_Zoom < 1.0f) m_Zoom = 1.0f;
    if (m_Zoom > 89.0f) m_Zoom = 89.0f;
}

// ===== 设置移动速度 =====
void Camera::SetSpeed(float moveSpeed, float rotateSpeed, float zoomSpeed) {
    m_MoveSpeed = moveSpeed;
    m_RotateSpeed = rotateSpeed;
    m_ZoomSpeed = zoomSpeed;
}

// ===== 更新方向向量 =====
void Camera::UpdateCameraVectors() {
    // 计算新的前向向量
    glm::vec3 front;
    front.x = cos(glm::radians(m_Yaw)) * cos(glm::radians(m_Pitch));
    front.y = sin(glm::radians(m_Pitch));
    front.z = sin(glm::radians(m_Yaw)) * cos(glm::radians(m_Pitch));
    m_Front = glm::normalize(front);

    // 计算右向量和上向量
    m_Right = glm::normalize(glm::cross(m_Front, m_WorldUp));
    m_Up = glm::normalize(glm::cross(m_Right, m_Front));
}

//===========================================================
// 文件: BoundingBox.cpp
// 路径: CandyRenderEngine/BoundingBox.cpp
// 说明: 包围盒实现文件
//===========================================================

#include "pch.h"
#include "BoundingBox.h"
#include <algorithm>
#include <cmath>

#ifndef FLT_MAX
#define FLT_MAX 3.402823466e+38F
#endif

BoundingBox::BoundingBox()
    : m_Min(FLT_MAX, FLT_MAX, FLT_MAX)
    , m_Max(-FLT_MAX, -FLT_MAX, -FLT_MAX) {
}

BoundingBox::BoundingBox(const glm::vec3& min, const glm::vec3& max)
    : m_Min(min)
    , m_Max(max) {
}

void BoundingBox::Merge(const BoundingBox& other) {
    if (!other.IsValid()) return;

    m_Min.x = (std::min)(m_Min.x, other.m_Min.x);
    m_Min.y = (std::min)(m_Min.y, other.m_Min.y);
    m_Min.z = (std::min)(m_Min.z, other.m_Min.z);

    m_Max.x = (std::max)(m_Max.x, other.m_Max.x);
    m_Max.y = (std::max)(m_Max.y, other.m_Max.y);
    m_Max.z = (std::max)(m_Max.z, other.m_Max.z);
}

void BoundingBox::Merge(const glm::vec3& point) {
    m_Min.x = (std::min)(m_Min.x, point.x);
    m_Min.y = (std::min)(m_Min.y, point.y);
    m_Min.z = (std::min)(m_Min.z, point.z);

    m_Max.x = (std::max)(m_Max.x, point.x);
    m_Max.y = (std::max)(m_Max.y, point.y);
    m_Max.z = (std::max)(m_Max.z, point.z);
}

void BoundingBox::Reset() {
    m_Min = glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX);
    m_Max = glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
}

BoundingBox BoundingBox::Transform(const glm::mat4& matrix) const {
    if (!IsValid()) return BoundingBox();

    glm::vec3 corners[8];
    GetCorners(corners);

    BoundingBox result;
    for (int i = 0; i < 8; ++i) {
        glm::vec4 transformed = matrix * glm::vec4(corners[i], 1.0f);
        result.Merge(glm::vec3(transformed.x, transformed.y, transformed.z));
    }

    return result;
}

bool BoundingBox::Intersects(const BoundingBox& other) const {
    if (!IsValid() || !other.IsValid()) return false;

    return (m_Min.x <= other.m_Max.x && m_Max.x >= other.m_Min.x) &&
        (m_Min.y <= other.m_Max.y && m_Max.y >= other.m_Min.y) &&
        (m_Min.z <= other.m_Max.z && m_Max.z >= other.m_Min.z);
}

bool BoundingBox::Contains(const glm::vec3& point) const {
    if (!IsValid()) return false;

    return (point.x >= m_Min.x && point.x <= m_Max.x) &&
        (point.y >= m_Min.y && point.y <= m_Max.y) &&
        (point.z >= m_Min.z && point.z <= m_Max.z);
}

bool BoundingBox::IsOnFrustum(const glm::vec4 planes[6]) const {
    if (!IsValid()) return false;

    glm::vec3 corners[8];
    GetCorners(corners);

    for (int i = 0; i < 6; ++i) {
        const glm::vec4& plane = planes[i];
        bool allOutside = true;

        for (int j = 0; j < 8; ++j) {
            float distance = plane.x * corners[j].x + plane.y * corners[j].y +
                plane.z * corners[j].z + plane.w;
            if (distance >= 0) {
                allOutside = false;
                break;
            }
        }

        if (allOutside) return false;
    }

    return true;
}

float BoundingBox::GetRadius() const {
    if (!IsValid()) return 0.0f;
    return glm::distance(GetCenter(), m_Max);
}

float BoundingBox::GetVolume() const {
    if (!IsValid()) return 0.0f;
    glm::vec3 size = GetSize();
    return size.x * size.y * size.z;
}

void BoundingBox::GetCorners(glm::vec3 corners[8]) const {
    corners[0] = glm::vec3(m_Min.x, m_Min.y, m_Min.z);
    corners[1] = glm::vec3(m_Max.x, m_Min.y, m_Min.z);
    corners[2] = glm::vec3(m_Min.x, m_Max.y, m_Min.z);
    corners[3] = glm::vec3(m_Max.x, m_Max.y, m_Min.z);
    corners[4] = glm::vec3(m_Min.x, m_Min.y, m_Max.z);
    corners[5] = glm::vec3(m_Max.x, m_Min.y, m_Max.z);
    corners[6] = glm::vec3(m_Min.x, m_Max.y, m_Max.z);
    corners[7] = glm::vec3(m_Max.x, m_Max.y, m_Max.z);
}

...全文
30 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

3

社区成员

发帖
与我相关
我的任务
社区描述
openTK、OpenGL、WebGL技术学习交流
图形渲染c#程序人生 技术论坛(原bbs) 广东省·深圳市
社区管理员
  • 亿只小灿灿
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧