summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/components.hpp9
-rw-r--r--src/ecs.cpp62
-rw-r--r--src/ecs.hpp3
-rw-r--r--src/game-settings.hpp1
-rw-r--r--src/game.cpp6
5 files changed, 77 insertions, 4 deletions
diff --git a/src/components.hpp b/src/components.hpp
index 4d52e39..3e7521f 100644
--- a/src/components.hpp
+++ b/src/components.hpp
@@ -4,6 +4,9 @@
#include "macros.hpp"
#include "dynamic-array.hpp"
+#include <BulletCollision/CollisionShapes/btCollisionShape.h>
+#include <LinearMath/btDefaultMotionState.h>
+#include <BulletDynamics/Dynamics/btRigidBody.h>
#include <glm/gtc/quaternion.hpp>
#include <vulkan/vulkan_core.h>
@@ -63,6 +66,12 @@ struct CompInstance {
InstanceHandle instanceHandle = InstanceHandle_MAX;
uint64_t index = ECS_UNSET_VAL;
InstPos instPos;
+ struct {
+ btVector3 localInertia;
+ btCollisionShape *collisionShape;
+ btDefaultMotionState defaultMotionState;
+ btRigidBody *rigidBody;
+ } bt;
bool isNeedingUpdated = false;
};
diff --git a/src/ecs.cpp b/src/ecs.cpp
index 3c5cbdb..831adfb 100644
--- a/src/ecs.cpp
+++ b/src/ecs.cpp
@@ -1,12 +1,18 @@
#include "ecs.hpp"
+#include "game-settings.hpp"
#include "memory.hpp"
#include "vendor/glm_include.hpp"
#include "window.hpp"
#include <btBulletDynamicsCommon.h>
+#define GLM_TO_BULLET_VEC_3(vec) btVector3(vec.x, vec.y, vec.z)
+#define GLM_TO_BULLET_QUAT(quat) btQuaternion(quat.x, quat.y, quat.z, quat.w)
+#define BULLET_TO_GLM_VEC_3(vec) glm::vec3(vec.getX(), vec.getY(), vec.getZ())
+#define BULLET_TO_GLM_QUAT(qt) glm::quat(qt.getW(), qt.getX(), qt.getY(), qt.getZ())
+
TypeSafeInt_B(EntityHandle);
const uint64_t maxBucketItemCount = 256;
@@ -178,6 +184,29 @@ void ECS_Tick_Early(double delta) {
entitiesMarkedForRemoval.Resize(0);
}
+void ECS_Tick(double delta) {
+ if (btDynamicsWorld && pkeSettings.isSimulationPaused == false) {
+ auto physicsTickCount = btDynamicsWorld->stepSimulation(delta, 0);
+ if (physicsTickCount != 0) {
+ for (long b = 0; b <= Comp_Instance_BucketContainer.bucketCounter; ++b) {
+ auto &bkt = Comp_Instance_BucketContainer.buckets[b];
+ long count = Comp_Instance_BucketContainer.bucketCounter == b ? Comp_Instance_BucketContainer.itemCounter >> 32 : maxBucketItemCount;
+ for (uint32_t i = 0; i < count; ++i) {
+ auto &inst = bkt.instances[i];
+ btTransform trans;
+ inst.bt.defaultMotionState.getWorldTransform(trans);
+
+ InstPos instPos = inst.instPos;
+ instPos.pos = BULLET_TO_GLM_VEC_3(trans.getOrigin());
+ instPos.rot = BULLET_TO_GLM_QUAT(trans.getRotation());
+ // TODO add an _INNER since we have a reference to the object that this looks up
+ ECS_UpdateInstance(inst.entHandle, instPos, false);
+ }
+ }
+ }
+ }
+}
+
struct InstanceBufferCopyChunk {
uint64_t startingIndex;
uint64_t endingIndex;
@@ -374,6 +403,22 @@ CompInstance &ECS_CreateInstance(EntityHandle entHandle, EntityHandle entityType
if (grBinds->instanceCounter > grBinds->instanceBufferMaxCount) {
EntitiesWithExcessInstances.Push(grBinds->entHandle);
}
+
+ if (btDynamicsWorld) {
+ comp->bt.localInertia = btVector3(0, 0, 0);
+ comp->bt.collisionShape = Pke_New<btBoxShape>(bulletBucket);
+ new (comp->bt.collisionShape) btBoxShape(GLM_TO_BULLET_VEC_3(comp->instPos.scale));
+ comp->bt.collisionShape->calculateLocalInertia(btScalar(1.f), comp->bt.localInertia);
+ btTransform transform;
+ transform.setIdentity();
+ transform.setOrigin(GLM_TO_BULLET_VEC_3(comp->instPos.pos));
+ comp->bt.defaultMotionState = btDefaultMotionState(transform);
+ comp->bt.rigidBody = Pke_New<btRigidBody>(bulletBucket);
+ new (comp->bt.rigidBody) btRigidBody(btScalar(1.f), &comp->bt.defaultMotionState, comp->bt.collisionShape, comp->bt.localInertia);
+ btDynamicsWorld->addRigidBody(comp->bt.rigidBody);
+ comp->bt.rigidBody->setUserPointer(reinterpret_cast<void *>(comp->entHandle));
+ }
+
return *comp;
}
@@ -392,7 +437,7 @@ CompInstance *ECS_GetInstance(EntityHandle entHandle) {
return inst;
}
-void ECS_UpdateInstance(EntityHandle entHandle, const InstPos &instPos) {
+void ECS_UpdateInstance(EntityHandle entHandle, const InstPos &instPos, bool overridePhysics) {
Entity *ent = nullptr;
ECS_GetEntity_Inner(entHandle, ent);
@@ -404,10 +449,25 @@ void ECS_UpdateInstance(EntityHandle entHandle, const InstPos &instPos) {
auto i = Buckets_GetItemIndex(instanceHandle_t);
auto *inst = &Comp_Instance_BucketContainer.buckets[b].instances[i];
+ if (overridePhysics == false
+ && instPos.pos == inst->instPos.pos
+ && instPos.rot == inst->instPos.rot
+ && instPos.scale == inst->instPos.scale) {
+ return;
+ }
+
inst->instPos.pos = instPos.pos;
inst->instPos.rot = instPos.rot;
inst->instPos.scale = instPos.scale;
inst->isNeedingUpdated = true;
+
+ if (overridePhysics == true && btDynamicsWorld) {
+ btTransform transform;
+ transform.setIdentity();
+ transform.setOrigin(GLM_TO_BULLET_VEC_3(inst->instPos.pos));
+ transform.setRotation(GLM_TO_BULLET_QUAT(inst->instPos.rot));
+ inst->bt.rigidBody->setWorldTransform(transform);
+ }
}
uint64_t ECS_GetInstances_BucketCount() {
diff --git a/src/ecs.hpp b/src/ecs.hpp
index 49d947c..480ba0c 100644
--- a/src/ecs.hpp
+++ b/src/ecs.hpp
@@ -20,6 +20,7 @@ static struct {
void ECS_Init();
void ECS_Teardown();
void ECS_Tick_Early(double delta);
+void ECS_Tick(double delta);
void ECS_Tick_Late(double delta);
EntityHandle ECS_CreateEntity(EntityHandle parentEntHandle = EntityHandle{EntityHandle_T{0xFFFFFFFFFFFFFFFF}});
void ECS_MarkForRemoval(EntityHandle entHandle);
@@ -33,7 +34,7 @@ CompGrBinds *ECS_GetGrBinds(uint64_t bucketIndex, uint64_t &itemCount);
CompInstance &ECS_CreateInstance(EntityHandle entHandle, EntityHandle entityTypeEntityHandle);
CompInstance *ECS_GetInstance(EntityHandle entHandle);
-void ECS_UpdateInstance(EntityHandle entHandle, const InstPos &instPos);
+void ECS_UpdateInstance(EntityHandle entHandle, const InstPos &instPos, bool overridePhysics = false);
uint64_t ECS_GetInstances_BucketCount();
CompInstance *ECS_GetInstances(uint64_t bucketIndex, uint64_t &itemCount);
diff --git a/src/game-settings.hpp b/src/game-settings.hpp
index c42b917..1131e6d 100644
--- a/src/game-settings.hpp
+++ b/src/game-settings.hpp
@@ -9,6 +9,7 @@ struct GameSettings {
bool isGamePaused = false;
bool isShowingEditor = true;
bool isRenderingDebug = false;
+ bool isSimulationPaused = false;
std::chrono::steady_clock steadyClock;
int64_t targetFPS = 144;
int64_t minFPS = 20;
diff --git a/src/game.cpp b/src/game.cpp
index e921b2f..a1ba28b 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -247,7 +247,7 @@ void ParseInstance(std::ifstream &stream) {
const auto &et = GlobalEntityTypes[existingEntityTypeIndex];
auto entityHandle = ECS_CreateEntity();
ECS_CreateInstance(entityHandle, et.entityHandle);
- ECS_UpdateInstance(entityHandle, comp.instPos);
+ ECS_UpdateInstance(entityHandle, comp.instPos, true);
break;
}
if (strstr(readLine, PKE_FILE_INSTANCE_ENTITY_HANDLE)) {
@@ -422,6 +422,7 @@ void Game_Tick(double delta) {
EntityHandle newEntity = ECS_CreateEntity();
ECS_CreateInstance(newEntity, createInfo.entityTypeEntityHandle);
}
+
PkeInput_Tick(delta);
PkeInputEventHolder holder = PkeInput_Query(dbgCtrl_UnlockCamera);
if (holder.type != InputEventHash{0}) {
@@ -573,6 +574,7 @@ void RecordImGuiEditorWrapper() {
}
if (ImGui::BeginMenu("Debug")) {
ImGui::Checkbox("Show Debug Hitboxes", &pkeSettings.isRenderingDebug);
+ ImGui::Checkbox("Pause Physics Simulation", &pkeSettings.isSimulationPaused);
if (ImGui::Checkbox("Uncap Framerate", &pkeSettings.graphicsSettings.isFramerateUnlocked)) {
shouldRecreateSwapchain = true;
}
@@ -815,7 +817,7 @@ void RecordImGui_CompInstPos(bool readonly, CompInstance *component) {
changed = ImGui::InputScalarN("scale", ImGuiDataType_Float, &component->instPos.scale, 3, nullptr, nullptr, nullptr, inputTextFlags) || changed;
if (changed) {
- ECS_UpdateInstance(component->entHandle, component->instPos);
+ ECS_UpdateInstance(component->entHandle, component->instPos, true);
}
ImGui::Spacing();