#pragma once #include #include #include #include #include #include #include #include "ThreadPool.h" #include // Forward declarations class Primitive; class GameObject; class Engine { public: Engine(int window_width = 1280, int window_height = 720, const char* title = "C++ Engine"); virtual ~Engine(); virtual bool OnInitialize(); virtual void OnShutdown(); virtual void OnUpdate(float delta_time); virtual void OnRender(); void Run(); // Primitive factory methods std::shared_ptr CreateCube(const glm::vec3& color = glm::vec3(1.0f)); std::shared_ptr CreateSphere(int segments = 32, const glm::vec3& color = glm::vec3(1.0f)); std::shared_ptr CreatePlane(float width = 2.0f, float height = 2.0f, const glm::vec3& color = glm::vec3(1.0f)); std::shared_ptr CreateGrid(int size = 20, float spacing = 1.0f, const glm::vec3& color = glm::vec3(0.6f)); std::shared_ptr CreateOBJModel(const std::string& objPath, const std::string& texturePath = ""); // GameObject management std::shared_ptr CreateGameObject(std::shared_ptr primitive, const glm::vec3& position = glm::vec3(0.0f)); void AddGameObject(std::shared_ptr obj); void RemoveGameObject(std::shared_ptr obj); // Camera control void SetCameraPosition(const glm::vec3& position); void SetCameraTarget(const glm::vec3& target); void SetCameraOrbit(float distance, float angle, float height = 5.0f); GLuint text_vao = 0, text_vbo = 0; GLFWwindow* GetWindow() const { return window_; } float GetTime() const { return (float)glfwGetTime(); } private: ThreadPool threadPool_; // Culling result structure struct CullingBatch { Primitive* primitive; std::vector modelMatrices; }; using CullingResult = std::vector; // Helper methods CullingResult CullObjectsSubset( const std::vector& objects, size_t startIdx, size_t endIdx, const glm::mat4& viewProjection ); void MergeCullingResults( const std::vector& results, std::unordered_map>& outBatches ); static bool CullSphere(const glm::mat4& vp, const glm::vec3& center, float radius); protected: void InitializeShader(); void RenderScene(); void RenderSceneInstanced(); void RenderOverlay(); void RenderOverlayTestPoint(); void InitOverlay(); static void FramebufferSizeCallback(GLFWwindow* window, int width, int height); int width_, height_; GLFWwindow* window_; float last_time_ = 0.0f; // Camera glm::vec3 camera_position_ = glm::vec3(0, 5, 10); glm::vec3 camera_target_ = glm::vec3(0, 0, 0); glm::vec3 camera_up_ = glm::vec3(0, 1, 0); // Rendering GLuint shader_program_ = 0; std::vector> game_objects_; // Overlay VAO/VBO GLuint overlay_vao = 0; GLuint overlay_vbo = 0; GLuint overlay_program = 0; // Performance stats static constexpr int PERF_HISTORY = 300; float perf_times[PERF_HISTORY] = {0}; int perf_pos = 0; int perf_count = 0; // Projection matrix for overlay glm::mat4 ortho2D; // Font buffer for stb_easy_font static const int FONT_BUFFER_SIZE = 9999; char font_buffer[FONT_BUFFER_SIZE]; }; // Primitive base class class Primitive { public: virtual ~Primitive() = default; virtual void Render() = 0; virtual void Bind() = 0; virtual void Cleanup() = 0; virtual GLenum GetDrawMode() const { return GL_TRIANGLES; } virtual GLsizei GetIndexCount() const { return index_count_; } virtual GLsizei GetVertexCount() const { return vertex_count_; } virtual void Bind() const { glBindVertexArray(vao_); } protected: GLuint vao_ = 0; GLuint vbo_ = 0; GLuint ebo_ = 0; GLsizei index_count_ = 0; GLsizei vertex_count_ = 0; GLenum draw_mode_ = GL_TRIANGLES; glm::vec3 color_; }; // GameObject class class GameObject { public: GameObject(std::shared_ptr prim, const glm::vec3& pos); // Add: Primitive* GetPrimitive() const { return primitive_.get(); } float GetBoundingRadius() const; glm::vec3 GetPosition() const { return position_; } glm::mat4 GetModelMatrix() const; void Render(); void Cleanup(); void SetPosition(const glm::vec3& p) { position_ = p; } void SetRotation(const glm::vec3& r) { rotation_ = r; } void SetScale(const glm::vec3& s) { scale_ = s; } private: std::shared_ptr primitive_; glm::vec3 position_; glm::vec3 rotation_; glm::vec3 scale_{1.0f}; };