这是一个可以完美复原大唐风土人情的VR项目!!!!!

 

 

这里只是最初的测试版本,需要下载多个库,以后会有更多方法

 

:

 

// TangDynastyVR_Complete.h
#pragma once

#include <openvr.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <vector>
#include <memory>
#include <string>
#include <map>
#include <random>

// 情感状态枚举
enum class EmotionalState {
    NEUTRAL, JOYFUL, ANGRY, SAD, POETIC, NOSTALGIC, PROUD
};

// 对话消息结构
struct DialogueMessage {
    std::string speakerName;
    std::string content;
    float displayTime;
    glm::vec3 speakerPosition;
    bool isHistoricalFigure;
};

// 基础场景对象
class SceneObject {
public:
    virtual ~SceneObject() = default;
    virtual void render(const glm::mat4& view, const glm::mat4& projection) = 0;
    virtual void update(float deltaTime) = 0;
};

// 唐朝人物基类
class TangCharacter : public SceneObject {
protected:
    glm::vec3 position;
    glm::mat4 modelMatrix;
    GLuint VAO, VBO;
    float animationTime = 0.0f;
    
public:
    TangCharacter(const glm::vec3& pos) : position(pos) {}
    virtual ~TangCharacter() = default;
    
    void update(float deltaTime) override {
        animationTime += deltaTime;
        // 基础动画逻辑
    }
    
    void render(const glm::mat4& view, const glm::mat4& projection) override {
        // 基础渲染逻辑
    }
};

// 人物性格系统
class HistoricalPersonality {
private:
    std::map<EmotionalState, std::vector<std::string>> dialogues;
    EmotionalState currentState = EmotionalState::NEUTRAL;
    
public:
    void setDialogues(EmotionalState state, const std::vector<std::string>& lines) {
        dialogues[state] = lines;
    }
    
    std::string speak(EmotionalState state) {
        currentState = state;
        auto& stateDialogues = dialogues[state];
        if (stateDialogues.empty()) return "";
        
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<> dis(0, stateDialogues.size() - 1);
        return stateDialogues[dis(gen)];
    }
    
    EmotionalState getCurrentState() const { return currentState; }
};

// 增强的唐朝人物类
class EnhancedTangCharacter : public TangCharacter {
private:
    std::string characterName;
    std::string characterType;
    HistoricalPersonality personality;
    EmotionalState currentEmotion;
    float emotionChangeTimer = 0;
    float speakCooldown = 0;
    bool canSpeak = true;
    
public:
    EnhancedTangCharacter(const std::string& name, const std::string& type, const glm::vec3& pos)
        : TangCharacter(pos), characterName(name), characterType(type), 
          currentEmotion(EmotionalState::NEUTRAL) {
        initializePersonality();
    }
    
    void initializePersonality() {
        if (characterType == "libai") {
            personality.setDialogues(EmotionalState::POETIC, {
                "李白:(举杯邀月)人生得意须尽欢,莫使金樽空对月!这月色如此美好,当浮一大白!",
                "李白:我本楚狂人,凤歌笑孔丘。手持绿玉杖,朝别黄鹤楼。哈哈哈!痛快!"
            });
            personality.setDialogues(EmotionalState::JOYFUL, {
                "李白:今日得见知己,当痛饮三百杯!店家,再上酒来!",
                "李白:这长安繁华,盛唐气象,能生于此世,实乃我辈之幸!"
            });
            personality.setDialogues(EmotionalState::SAD, {
                "李白:(叹息)大道如青天,我独不得出...这满腹才华,何时才能得遇明主?",
                "李白:花间一壶酒,独酌无相亲。举杯邀明月,对影成三人...寂寞啊寂寞。"
            });
        } else if (characterType == "dufu") {
            personality.setDialogues(EmotionalState::SAD, {
                "杜甫:(忧心忡忡)朱门酒肉臭,路有冻死骨...这世道,百姓苦啊!",
                "杜甫:国破山河在,城春草木深。感时花溅泪,恨别鸟惊心...大唐何时才能重振?"
            });
            personality.setDialogues(EmotionalState::ANGRY, {
                "杜甫:(愤慨)官军收洛阳,家住洛阳里。夫婿与兄弟,目前见伤死!这战乱何时休!"
            });
        } else if (characterType == "merchant") {
            personality.setDialogues(EmotionalState::NEUTRAL, {
                "西域商人:(展示货物)来自波斯的琉璃,大食的香料,都是上等货色!",
                "西域商人:这丝绸之路真是黄金之路啊!从长安到罗马,处处是商机!"
            });
        }
    }
    
    void update(float deltaTime) override {
        TangCharacter::update(deltaTime);
        
        // 情绪状态变化
        emotionChangeTimer -= deltaTime;
        if (emotionChangeTimer <= 0) {
            changeEmotionRandomly();
            emotionChangeTimer = 10.0f + (rand() % 20);
        }
        
        // 说话冷却
        if (!canSpeak) {
            speakCooldown -= deltaTime;
            if (speakCooldown <= 0) canSpeak = true;
        }
    }
    
    void changeEmotionRandomly() {
        if (characterType == "libai") {
            std::vector<EmotionalState> emotions = {
                EmotionalState::POETIC, EmotionalState::JOYFUL, EmotionalState::POETIC, EmotionalState::NOSTALGIC
            };
            currentEmotion = emotions[rand() % emotions.size()];
        } else if (characterType == "dufu") {
            std::vector<EmotionalState> emotions = {
                EmotionalState::SAD, EmotionalState::ANGRY, EmotionalState::NOSTALGIC, EmotionalState::SAD
            };
            currentEmotion = emotions[rand() % emotions.size()];
        }
    }
    
    void speak(class DialogueUIManager& dialogueManager) {
        if (!canSpeak) return;
        
        std::string dialogue = personality.speak(currentEmotion);
        if (!dialogue.empty()) {
            dialogueManager.addMessage(characterName, dialogue, position, true);
            speakCooldown = 8.0f + (rand() % 7);
            canSpeak = false;
        }
    }
    
    const std::string& getName() const { return characterName; }
};

// 对话UI管理器
class DialogueUIManager {
private:
    struct DialogueUI {
        GLuint VAO, VBO, EBO;
        GLuint texture;
        glm::vec2 position = glm::vec2(0.1f, 0.1f);
        glm::vec2 size = glm::vec2(0.8f, 0.2f);
        bool isVisible = false;
    };

    DialogueUI dialogueUI;
    std::vector<DialogueMessage> messageQueue;
    DialogueMessage currentMessage;
    float messageTimer = 0;
    bool isShowingMessage = false;
    GLuint shaderProgram;
    
public:
    DialogueUIManager() = default;
    
    bool initialize() {
        createDialogueBackground();
        
        const char* vs = R"(
            #version 330 core
            layout(location = 0) in vec2 aPos;
            uniform vec2 uScreenSize;
            void main() {
                vec2 normalizedPos = aPos / uScreenSize;
                gl_Position = vec4(normalizedPos * 2.0 - 1.0, 0.0, 1.0);
            }
        )";
        
        const char* fs = R"(
            #version 330 core
            out vec4 FragColor;
            uniform vec4 uColor;
            void main() {
                FragColor = uColor;
            }
        )";
        
        // shaderProgram = ShaderManager::compileShaders(vs, fs);
        return true; // shaderProgram != 0;
    }
    
    void createDialogueBackground() {
        float x = dialogueUI.position.x, y = dialogueUI.position.y;
        float w = dialogueUI.size.x, h = dialogueUI.size.y;
        
        float vertices[] = { x, y, x+w, y, x+w, y+h, x, y+h };
        unsigned int indices[] = { 0, 1, 2, 2, 3, 0 };
        
        glGenVertexArrays(1, &dialogueUI.VAO);
        glGenBuffers(1, &dialogueUI.VBO);
        glGenBuffers(1, &dialogueUI.EBO);
        
        glBindVertexArray(dialogueUI.VAO);
        glBindBuffer(GL_ARRAY_BUFFER, dialogueUI.VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dialogueUI.EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
    }
    
    void addMessage(const std::string& speaker, const std::string& content, 
                   const glm::vec3& position = glm::vec3(0), bool isHistorical = false) {
        DialogueMessage msg{speaker, content, 5.0f, position, isHistorical};
        messageQueue.push_back(msg);
    }
    
    void update(float deltaTime) {
        if (isShowingMessage) {
            messageTimer -= deltaTime;
            if (messageTimer <= 0) {
                isShowingMessage = false;
                dialogueUI.isVisible = false;
            }
        }
        
        if (!isShowingMessage && !messageQueue.empty()) {
            currentMessage = messageQueue.front();
            messageQueue.erase(messageQueue.begin());
            
            dialogueUI.isVisible = true;
            isShowingMessage = true;
            messageTimer = currentMessage.displayTime;
        }
    }
    
    void render() {
        if (!dialogueUI.isVisible) return;
        
        glUseProgram(shaderProgram);
        glBindVertexArray(dialogueUI.VAO);
        
        // 设置uniform并渲染
        GLint screenSizeLoc = glGetUniformLocation(shaderProgram, "uScreenSize");
        glUniform2f(screenSizeLoc, 1920.0f, 1080.0f);
        glUniform4f(glGetUniformLocation(shaderProgram, "uColor"), 0.0f, 0.0f, 0.0f, 0.7f);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        
        // 这里应该渲染文本
        // renderText(currentMessage.speakerName + ":" + currentMessage.content, ...);
    }
};

// 主VR应用类
class TangDynastyVRApp {
private:
    GLFWwindow* window;
    vr::IVRSystem* vrSystem;
    
    // 渲染资源
    GLuint leftEyeFramebuffer, rightEyeFramebuffer;
    GLuint leftEyeTexture, rightEyeTexture;
    
    // 场景管理
    std::vector<std::shared_ptr<SceneObject>> sceneObjects;
    std::vector<std::shared_ptr<EnhancedTangCharacter>> characters;
    DialogueUIManager dialogueManager;
    
    // 着色器
    GLuint shaderProgram;
    
public:
    TangDynastyVRApp() : window(nullptr), vrSystem(nullptr), shaderProgram(0) {}
    
    bool initialize() {
        if (!initializeOpenGL() || !initializeVR()) return false;
        
        setupVRRenderTargets();
        dialogueManager.initialize();
        initializeScene();
        
        return true;
    }
    
    bool initializeOpenGL() {
        if (!glfwInit()) return false;
        
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
        window = glfwCreateWindow(800, 600, "唐朝VR体验", nullptr, nullptr);
        
        if (!window) {
            glfwTerminate();
            return false;
        }
        
        glfwMakeContextCurrent(window);
        return glewInit() == GLEW_OK;
    }
    
    bool initializeVR() {
        vr::EVRInitError error = vr::VRInitError_None;
        vrSystem = vr::VR_Init(&error, vr::VRApplication_Scene);
        return error == vr::VRInitError_None;
    }
    
    void initializeScene() {
        // 创建历史人物
        auto liBai = std::make_shared<EnhancedTangCharacter>("李白", "libai", glm::vec3(2, 0, -3));
        auto duFu = std::make_shared<EnhancedTangCharacter>("杜甫", "dufu", glm::vec3(-2, 0, -3));
        auto merchant = std::make_shared<EnhancedTangCharacter>("西域商人", "merchant", glm::vec3(0, 0, -4));
        
        characters.push_back(liBai);
        characters.push_back(duFu);
        characters.push_back(merchant);
        
        // 添加到场景对象
        for (auto& character : characters) {
            sceneObjects.push_back(character);
        }
    }
    
    void setupVRRenderTargets() {
        // 创建VR渲染目标
        glGenFramebuffers(1, &leftEyeFramebuffer);
        glGenFramebuffers(1, &rightEyeFramebuffer);
        // ... 更多初始化代码
    }
    
    void run() {
        while (!glfwWindowShouldClose(window)) {
            glfwPollEvents();
            
            float deltaTime = 0.016f; // 假设60FPS
            
            // 更新所有对象
            for (auto& obj : sceneObjects) {
                obj->update(deltaTime);
            }
            
            // 随机触发对话
            for (auto& character : characters) {
                if (rand() % 600 < 1) { // 约每秒有1/600几率触发
                    character->speak(dialogueManager);
                }
            }
            
            dialogueManager.update(deltaTime);
            
            // VR渲染
            renderVRScene();
            
            glfwSwapBuffers(window);
        }
    }
    
    void renderVRScene() {
        // 渲染左眼
        glBindFramebuffer(GL_FRAMEBUFFER, leftEyeFramebuffer);
        renderEye(vr::Eye_Left);
        
        // 渲染右眼
        glBindFramebuffer(GL_FRAMEBUFFER, rightEyeFramebuffer);
        renderEye(vr::Eye_Right);
        
        // 提交到VR合成器
        // vr::VRCompositor()->Submit(...);
    }
    
    void renderEye(vr::Hmd_Eye eye) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // 设置视图和投影矩阵
        glm::mat4 view = getEyeViewMatrix(eye);
        glm::mat4 projection = getEyeProjectionMatrix(eye);
        
        // 渲染场景对象
        for (auto& obj : sceneObjects) {
            obj->render(view, projection);
        }
        
        // 渲染UI
        dialogueManager.render();
    }
    
    glm::mat4 getEyeViewMatrix(vr::Hmd_Eye eye) {
        // 获取VR眼睛视图矩阵
        return glm::mat4(1.0f);
    }
    
    glm::mat4 getEyeProjectionMatrix(vr::Hmd_Eye eye) {
        // 获取VR眼睛投影矩阵
        return glm::mat4(1.0f);
    }
    
    ~TangDynastyVRApp() {
        if (vrSystem) vr::VR_Shutdown();
        if (window) glfwDestroyWindow(window);
        glfwTerminate();
    }
};

// 主函数
int main() {
    TangDynastyVRApp app;
    
    if (app.initialize()) {
        std::cout << "启动唐朝VR体验..." << std::endl;
        app.run();
    }
    
    return 0;
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐