增加重力系统
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 "first_app.hpp"
|
||||||
#include "simple_render_system.hpp"
|
#include "simple_render_system.hpp"
|
||||||
|
#include "rainbow_system.hpp"
|
||||||
|
#include "gravity_physics_system.hpp"
|
||||||
|
|
||||||
// libs
|
// libs
|
||||||
#define GLM_FORCE_RADIANS
|
#define GLM_FORCE_RADIANS
|
||||||
|
@ -11,6 +13,7 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
|
||||||
namespace hk
|
namespace hk
|
||||||
{
|
{
|
||||||
FirstApp::FirstApp()
|
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()
|
void FirstApp::run()
|
||||||
{
|
{
|
||||||
SimpleRenderSystem simpleRenderSystem{m_device, m_renderer.getSwapChainRenderPass()};
|
SimpleRenderSystem simpleRenderSystem{m_device, m_renderer.getSwapChainRenderPass()};
|
||||||
|
RainbowSystem rainbowSystem(2000.0f);
|
||||||
|
|
||||||
while (!m_window.shouldClose())
|
while (!m_window.shouldClose())
|
||||||
{
|
{
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
|
// update objects color
|
||||||
|
rainbowSystem.update(5.0f, m_gameObjects);
|
||||||
|
|
||||||
if (auto commandBuffer = m_renderer.beginFrame())
|
if (auto commandBuffer = m_renderer.beginFrame())
|
||||||
{
|
{
|
||||||
m_renderer.beginSwapChainRenderPass(commandBuffer);
|
m_renderer.beginSwapChainRenderPass(commandBuffer);
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace hk
|
||||||
FirstApp &operator=(const FirstApp &) = delete;
|
FirstApp &operator=(const FirstApp &) = delete;
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
void runGravitySystem();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadGameObjects();
|
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
|
class GameObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -51,6 +57,8 @@ namespace hk
|
||||||
glm::vec3 m_color{};
|
glm::vec3 m_color{};
|
||||||
Transform2dComponent m_transform2d{};
|
Transform2dComponent m_transform2d{};
|
||||||
|
|
||||||
|
RigidBody2dComponent m_rigidBody2d{};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GameObject(id_t objId) : m_id(objId) {}
|
GameObject(id_t objId) : m_id(objId) {}
|
||||||
|
|
||||||
|
|
|
@ -423,14 +423,14 @@ namespace hk
|
||||||
VkPresentModeKHR SwapChain::chooseSwapPresentMode(
|
VkPresentModeKHR SwapChain::chooseSwapPresentMode(
|
||||||
const std::vector<VkPresentModeKHR> &availablePresentModes)
|
const std::vector<VkPresentModeKHR> &availablePresentModes)
|
||||||
{
|
{
|
||||||
// for (const auto &availablePresentMode : availablePresentModes)
|
for (const auto &availablePresentMode : availablePresentModes)
|
||||||
// {
|
{
|
||||||
// if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
|
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
|
||||||
// {
|
{
|
||||||
// std::cout << "Present mode: Mailbox" << std::endl;
|
std::cout << "Present mode: Mailbox" << std::endl;
|
||||||
// return availablePresentMode;
|
return availablePresentMode;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// for (const auto &availablePresentMode : availablePresentModes)
|
// for (const auto &availablePresentMode : availablePresentModes)
|
||||||
// {
|
// {
|
||||||
|
|
6
main.cpp
6
main.cpp
|
@ -5,13 +5,19 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#define GRAVITY_SYSTEM 1
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
hk::FirstApp app{};
|
hk::FirstApp app{};
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
#if GRAVITY_SYSTEM == 1
|
||||||
|
app.runGravitySystem();
|
||||||
|
#else
|
||||||
app.run();
|
app.run();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
catch(const std::exception& e)
|
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