增加重力系统
This commit is contained in:
		
							parent
							
								
									b9c5ec712d
								
							
						
					
					
						commit
						20224f19c3
					
				
							
								
								
									
										
											BIN
										
									
								
								VulkanTest
								
								
								
								
							
							
						
						
									
										
											BIN
										
									
								
								VulkanTest
								
								
								
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
#include "first_app.hpp"
 | 
			
		||||
#include "simple_render_system.hpp"
 | 
			
		||||
#include "rainbow_system.hpp"
 | 
			
		||||
#include "gravity_physics_system.hpp"
 | 
			
		||||
 | 
			
		||||
// libs
 | 
			
		||||
#define GLM_FORCE_RADIANS
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +13,7 @@
 | 
			
		|||
#include <stdexcept>
 | 
			
		||||
#include <array>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace hk
 | 
			
		||||
{
 | 
			
		||||
    FirstApp::FirstApp()
 | 
			
		||||
| 
						 | 
				
			
			@ -22,13 +25,84 @@ namespace hk
 | 
			
		|||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void FirstApp::runGravitySystem()
 | 
			
		||||
    {
 | 
			
		||||
        // Gravity Physics System 
 | 
			
		||||
        // Create some Models
 | 
			
		||||
        std::shared_ptr<Model> squareModel = createSquareModel(m_device, {.5f, .0f});
 | 
			
		||||
        std::shared_ptr<Model> circleModel = createCircleModel(m_device, 64);
 | 
			
		||||
        // Create Physics Objects
 | 
			
		||||
        std::vector<GameObject> physicsObjects{};
 | 
			
		||||
        auto red = GameObject::createGameObject();
 | 
			
		||||
        red.m_transform2d.scale = glm::vec2{.05f};
 | 
			
		||||
        red.m_transform2d.translation = {.5f, .5f};
 | 
			
		||||
        red.m_color = {1.f, 0.f, 0.f};
 | 
			
		||||
        red.m_rigidBody2d.velocity = {-.5f, .0f};
 | 
			
		||||
        red.m_model = circleModel;
 | 
			
		||||
        physicsObjects.push_back(std::move(red));
 | 
			
		||||
        auto blue = GameObject::createGameObject();
 | 
			
		||||
        blue.m_transform2d.scale = glm::vec2{.05f};
 | 
			
		||||
        blue.m_transform2d.translation = {-.45f, -.25f};
 | 
			
		||||
        blue.m_color = {0.f, 0.f, 1.f};
 | 
			
		||||
        blue.m_rigidBody2d.velocity = {.5f, .0f};
 | 
			
		||||
        blue.m_model = circleModel;
 | 
			
		||||
        physicsObjects.push_back(std::move(blue));
 | 
			
		||||
 | 
			
		||||
        // Create Vector Field 
 | 
			
		||||
        std::vector<GameObject> vectorField{};
 | 
			
		||||
        int gridCount = 40;
 | 
			
		||||
        for (int i = 0; i < gridCount; i++)
 | 
			
		||||
        {
 | 
			
		||||
            for(int j = 0; j < gridCount; j ++)
 | 
			
		||||
            {
 | 
			
		||||
                auto vf = GameObject::createGameObject();
 | 
			
		||||
                vf.m_transform2d.scale = glm::vec2{0.005f};
 | 
			
		||||
                vf.m_transform2d.translation = {-1.0f + (i + 0.5f) * 2.0f / gridCount, -1.0f + (j + 0.5f) * 2.0f / gridCount};
 | 
			
		||||
                vf.m_color = glm::vec3{1.0f};
 | 
			
		||||
                vf.m_model = squareModel;
 | 
			
		||||
                vectorField.push_back(std::move(vf));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        GravityPhysicsSystem gravitySystem(0.81f);
 | 
			
		||||
        Vec2FieldSystem vecFieldSystem{};
 | 
			
		||||
 | 
			
		||||
        SimpleRenderSystem simpleRenderSystem{m_device, m_renderer.getSwapChainRenderPass()};
 | 
			
		||||
 | 
			
		||||
        while(!m_window.shouldClose())
 | 
			
		||||
        {
 | 
			
		||||
            glfwPollEvents();
 | 
			
		||||
 | 
			
		||||
            if (auto commandBuffer = m_renderer.beginFrame())
 | 
			
		||||
            {
 | 
			
		||||
                // update system
 | 
			
		||||
                gravitySystem.update(physicsObjects, 1.f / 60, 5);
 | 
			
		||||
                vecFieldSystem.update(gravitySystem, physicsObjects, vectorField);
 | 
			
		||||
 | 
			
		||||
                // render system
 | 
			
		||||
                m_renderer.beginSwapChainRenderPass(commandBuffer);
 | 
			
		||||
                simpleRenderSystem.renderGameObjects(commandBuffer, physicsObjects);
 | 
			
		||||
                simpleRenderSystem.renderGameObjects(commandBuffer, vectorField);
 | 
			
		||||
                m_renderer.endSwapChainRenderPass(commandBuffer);
 | 
			
		||||
                m_renderer.endFrame();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            vkDeviceWaitIdle(m_device.device());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void FirstApp::run()
 | 
			
		||||
    {
 | 
			
		||||
        SimpleRenderSystem simpleRenderSystem{m_device, m_renderer.getSwapChainRenderPass()};
 | 
			
		||||
        RainbowSystem rainbowSystem(2000.0f);
 | 
			
		||||
 | 
			
		||||
        while (!m_window.shouldClose())
 | 
			
		||||
        {
 | 
			
		||||
            glfwPollEvents();
 | 
			
		||||
            
 | 
			
		||||
            // update objects color
 | 
			
		||||
            rainbowSystem.update(5.0f, m_gameObjects);
 | 
			
		||||
 | 
			
		||||
            if (auto commandBuffer = m_renderer.beginFrame())
 | 
			
		||||
            {
 | 
			
		||||
                m_renderer.beginSwapChainRenderPass(commandBuffer);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ namespace hk
 | 
			
		|||
        FirstApp &operator=(const FirstApp &) = delete;
 | 
			
		||||
 | 
			
		||||
        void run();
 | 
			
		||||
        void runGravitySystem();
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        void loadGameObjects();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,129 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <hk_game_object.hpp>
 | 
			
		||||
 | 
			
		||||
#define GLM_FORCE_RADIANS
 | 
			
		||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
 | 
			
		||||
#include <glm/glm.hpp>
 | 
			
		||||
#include <glm/gtc/constants.hpp>
 | 
			
		||||
 | 
			
		||||
// std
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <random>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace hk
 | 
			
		||||
{
 | 
			
		||||
    class GravityPhysicsSystem
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        GravityPhysicsSystem(float strength) :m_strengthGravity(strength) {}
 | 
			
		||||
 | 
			
		||||
        void update(std::vector<GameObject> &objs, float dt, unsigned int substeps = 1)
 | 
			
		||||
        {
 | 
			
		||||
            const float stepDelta = dt / substeps;
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < substeps; i++)
 | 
			
		||||
            {
 | 
			
		||||
                stepSimulation(objs, stepDelta);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        glm::vec2 computeForce(GameObject &fromObj, GameObject &toObj) const 
 | 
			
		||||
        {
 | 
			
		||||
            auto offset = fromObj.m_transform2d.translation - toObj.m_transform2d.translation;
 | 
			
		||||
            float distanceSquared = glm::dot(offset, offset);
 | 
			
		||||
 | 
			
		||||
            if (glm::abs(distanceSquared < 1e-10f))
 | 
			
		||||
            {
 | 
			
		||||
                return {.0f, .0f};
 | 
			
		||||
            }
 | 
			
		||||
            float force = m_strengthGravity * toObj.m_rigidBody2d.mass * fromObj.m_rigidBody2d.mass / distanceSquared;
 | 
			
		||||
 | 
			
		||||
            return force * offset / glm::sqrt(distanceSquared);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const float m_strengthGravity;
 | 
			
		||||
    private:
 | 
			
		||||
        void stepSimulation(std::vector<GameObject> &physicsObjs, float dt)
 | 
			
		||||
        {
 | 
			
		||||
            // Loops throught all pairs of objects and applies attractive force between them
 | 
			
		||||
            for (auto iterA = physicsObjs.begin(); iterA != physicsObjs.end(); ++iterA)
 | 
			
		||||
            {
 | 
			
		||||
                auto &objA = *iterA;
 | 
			
		||||
                for (auto iterB = iterA; iterB != physicsObjs.end(); ++iterB)
 | 
			
		||||
                {
 | 
			
		||||
                    if (iterA == iterB) continue;
 | 
			
		||||
 | 
			
		||||
                    auto &objB = *iterB;
 | 
			
		||||
                    auto force = computeForce(objA, objB);
 | 
			
		||||
                    objA.m_rigidBody2d.velocity += dt * -force / objA.m_rigidBody2d.mass;
 | 
			
		||||
                    objB.m_rigidBody2d.velocity += dt * force / objB.m_rigidBody2d.mass;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // update each objects position based on its final velocity
 | 
			
		||||
            for (auto &obj : physicsObjs)
 | 
			
		||||
            {
 | 
			
		||||
                obj.m_transform2d.translation += dt * obj.m_rigidBody2d.velocity;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class Vec2FieldSystem
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        void update(const GravityPhysicsSystem &physicsSystem, std::vector<GameObject> &physicsObjs, std::vector<GameObject> &vectorField)
 | 
			
		||||
        {
 | 
			
		||||
            for (auto &vf : vectorField)
 | 
			
		||||
            {
 | 
			
		||||
                glm::vec2 direction{};
 | 
			
		||||
                for (auto &obj : physicsObjs)
 | 
			
		||||
                {
 | 
			
		||||
                    direction += physicsSystem.computeForce(obj, vf);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                vf.m_transform2d.scale.x = 0.005f + 0.045f * glm::clamp(glm::log(glm::length(direction) + 1) / 3.f, 0.f, 1.f);
 | 
			
		||||
                vf.m_transform2d.rotation = atan2(direction.y, direction.x);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<Model> createSquareModel(Device &device, glm::vec2 offset)
 | 
			
		||||
    {
 | 
			
		||||
        std::vector<Model::Vertex> vertices = {
 | 
			
		||||
            {{-0.5f, -0.5f}}, {{0.5f, 0.5f}},
 | 
			
		||||
            {{-0.5f, 0.5f}}, {{-0.5f, -0.5f}},
 | 
			
		||||
            {{0.5f, -0.5f}}, {{0.5f, 0.5f}},
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        for (auto &v : vertices)
 | 
			
		||||
        {
 | 
			
		||||
            v.posision += offset;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return std::make_unique<Model>(device, vertices);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<Model> createCircleModel(Device &device, unsigned int numSides)
 | 
			
		||||
    {
 | 
			
		||||
        std::vector<Model::Vertex> uniqueVertices{};
 | 
			
		||||
        for(int i = 0; i < numSides; i++)
 | 
			
		||||
        {
 | 
			
		||||
            float angle = i * glm::two_pi<float>() / numSides;
 | 
			
		||||
            uniqueVertices.push_back({{glm::cos(angle), glm::sin(angle)}});
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        uniqueVertices.push_back({});
 | 
			
		||||
 | 
			
		||||
        std::vector<Model::Vertex> vertices{};
 | 
			
		||||
        for(int i = 0; i < numSides; i++)
 | 
			
		||||
        {
 | 
			
		||||
            vertices.push_back(uniqueVertices[i]);
 | 
			
		||||
            vertices.push_back(uniqueVertices[(i+1) % numSides]);
 | 
			
		||||
            vertices.push_back(uniqueVertices[numSides]);
 | 
			
		||||
        }
 | 
			
		||||
        return std::make_unique<Model>(device, vertices);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -28,6 +28,12 @@ namespace hk
 | 
			
		|||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct RigidBody2dComponent
 | 
			
		||||
    {
 | 
			
		||||
        glm::vec2 velocity;
 | 
			
		||||
        float mass{1.0f};
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class GameObject
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
| 
						 | 
				
			
			@ -51,6 +57,8 @@ namespace hk
 | 
			
		|||
        glm::vec3 m_color{};
 | 
			
		||||
        Transform2dComponent m_transform2d{}; 
 | 
			
		||||
 | 
			
		||||
        RigidBody2dComponent m_rigidBody2d{};
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        GameObject(id_t objId) : m_id(objId) {}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -423,14 +423,14 @@ namespace hk
 | 
			
		|||
  VkPresentModeKHR SwapChain::chooseSwapPresentMode(
 | 
			
		||||
      const std::vector<VkPresentModeKHR> &availablePresentModes)
 | 
			
		||||
  {
 | 
			
		||||
    // for (const auto &availablePresentMode : availablePresentModes)
 | 
			
		||||
    // {
 | 
			
		||||
    //   if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
 | 
			
		||||
    //   {
 | 
			
		||||
    //     std::cout << "Present mode: Mailbox" << std::endl;
 | 
			
		||||
    //     return availablePresentMode;
 | 
			
		||||
    //   }
 | 
			
		||||
    // }
 | 
			
		||||
    for (const auto &availablePresentMode : availablePresentModes)
 | 
			
		||||
    {
 | 
			
		||||
      if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
 | 
			
		||||
      {
 | 
			
		||||
        std::cout << "Present mode: Mailbox" << std::endl;
 | 
			
		||||
        return availablePresentMode;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // for (const auto &availablePresentMode : availablePresentModes)
 | 
			
		||||
    // {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								main.cpp
								
								
								
								
							
							
						
						
									
										6
									
								
								main.cpp
								
								
								
								
							| 
						 | 
				
			
			@ -5,13 +5,19 @@
 | 
			
		|||
#include <iostream>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
#define GRAVITY_SYSTEM 1
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    hk::FirstApp app{};
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
#if GRAVITY_SYSTEM == 1
 | 
			
		||||
        app.runGravitySystem();
 | 
			
		||||
#else
 | 
			
		||||
        app.run();
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
    catch(const std::exception& e)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <hk_game_object.hpp>
 | 
			
		||||
 | 
			
		||||
// std
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <random>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace hk
 | 
			
		||||
{
 | 
			
		||||
    class RainbowSystem
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        RainbowSystem(float flickerRate) : m_flickerRate(flickerRate)
 | 
			
		||||
        {
 | 
			
		||||
            // initialize colors
 | 
			
		||||
            m_color = {{.8f, .1f, .1f}, {.1f, .8f, .1f}, {.1f, .1f, .8f}, {.8f, .8f, .1f}, {.8f, .1f, .8f}, {.1f, .8f, .8f}};
 | 
			
		||||
            m_elapsedTime = m_flickerRate;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void update(float dt, std::vector<GameObject> &gameObjects)
 | 
			
		||||
        {
 | 
			
		||||
            m_elapsedTime -= dt;
 | 
			
		||||
            if (m_elapsedTime < 0.f)
 | 
			
		||||
            {
 | 
			
		||||
                std::uniform_int_distribution<int> randInt{0, static_cast<int>(m_color.size()) -1};
 | 
			
		||||
                for (auto &obj : gameObjects)
 | 
			
		||||
                {
 | 
			
		||||
                    int randValue = randInt(m_rng);
 | 
			
		||||
                    obj.m_color = m_color[randValue];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        std::random_device m_rd;
 | 
			
		||||
        std::mt19937 m_rng{m_rd()};
 | 
			
		||||
 | 
			
		||||
        std::vector<glm::vec3> m_color;
 | 
			
		||||
        float m_flickerRate;
 | 
			
		||||
        float m_elapsedTime;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue