summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2024-01-18 22:37:02 -0500
committerJonathan Bradley <jcb@pikum.xyz>2024-01-18 22:37:02 -0500
commit1b48d1382d2d57a822201f34743a51813798b348 (patch)
tree612672a4be654b38f3b44580f85e4f0637952512 /src
parent2e680ebd77236f7b62b9ded1b083c86f9e13b1c8 (diff)
camera checkpoint - large refactor for attempting to let physics own camera position
Diffstat (limited to 'src')
-rw-r--r--src/arg-handler.cpp1
-rw-r--r--src/array.hpp8
-rw-r--r--src/camera.cpp77
-rw-r--r--src/camera.hpp5
-rw-r--r--src/components.hpp6
-rw-r--r--src/entities.cpp1
-rw-r--r--src/game.cpp276
-rw-r--r--src/plugin-types.hpp25
-rw-r--r--src/plugins.hpp19
-rw-r--r--src/project.cpp1
-rw-r--r--src/window.cpp20
11 files changed, 250 insertions, 189 deletions
diff --git a/src/arg-handler.cpp b/src/arg-handler.cpp
index 2183347..3bd1ac3 100644
--- a/src/arg-handler.cpp
+++ b/src/arg-handler.cpp
@@ -35,7 +35,6 @@ void PkeArgs_Parse(int argc, char *argv[]) {
pkeSettings.args.sceneName = optarg;
pkeSettings.rt.shouldLoadScene = true;
pkeSettings.rt.sceneName = pkeSettings.args.sceneName;
- pkeSettings.rt.nextLevel = PkeLevel_Create("transient");
break;
default:
fprintf(stderr, "Unused parameter: %c\n", c);
diff --git a/src/array.hpp b/src/array.hpp
index f8aa173..7db2252 100644
--- a/src/array.hpp
+++ b/src/array.hpp
@@ -61,11 +61,11 @@ inline void PkeArray_Add(PkeArray_Base *arrIn, const D &val, MemBucket *bkt = nu
}
}
-template<typename D, typename F = bool(const D&)>
-inline uint32_t PkeArray_FindFirstIndex(PkeArray_Base *arrIn, F fn) {
+template<typename D, typename D2, typename F = bool(const D&, const D2&)>
+inline int64_t PkeArray_FindFirstIndex(PkeArray_Base *arrIn, F fn, const D2 &d2) {
auto *arr = static_cast<PkeArray<D> *>(arrIn);
- for (uint32_t i = 0; i < arr->next; ++i) {
- if (fn(arr->data[i])) {
+ for (int64_t i = 0; i < arr->next; ++i) {
+ if (fn(arr->data[i], d2)) {
return i;
}
}
diff --git a/src/camera.cpp b/src/camera.cpp
index 984f106..f033824 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -10,14 +10,12 @@
PkeCamera NullCamera {
.camHandle = CameraHandle_MAX,
- .pos = glm::vec3(3.f, 3.f, 3.f),
- .rot = glm::quat(1.f, 0.f, 0.f, 0.f),
- .target = glm::vec3(0.f),
.type = PKE_CAMERA_TYPE_ORTHOGONAL,
.view = PKE_CAMERA_VIEW_TARGET,
.stale = PKE_CAMERA_STALE_ALL,
.phys = {
.inst = nullptr,
+ .targetInst = nullptr,
.constraint = nullptr,
},
};
@@ -28,16 +26,7 @@ BucketContainer<PkeCamera, CameraHandle> Camera_BucketContainer{};
btSphereShape CameraShape{1.f};
-PkeCamera &PkeCamera_Register(const InstPos &instPos) {
- CameraHandle cameraHandle{Buckets_NewHandle(Camera_BucketContainer)};
-
- auto &cam = Camera_BucketContainer.buckets[cameraHandle.bucketIndex][cameraHandle.itemIndex];
- new (&cam) PkeCamera{};
-
- ECS_CreateEntity(&cam, nullptr);
- cam.camHandle = cameraHandle;
- cam.phys.inst = ECS_CreateInstance(&cam, nullptr);
-
+PkeCamera &PkeCamera_Register_Inner(PkeCamera &cam, const InstPos &instPos) {
btVector3 gravity(0.f, 0.f, 0.f);
cam.phys.inst->physicsLayer = PhysicsCollision{0};
@@ -63,11 +52,38 @@ PkeCamera &PkeCamera_Register(const InstPos &instPos) {
return cam;
}
+PkeCamera &PkeCamera_Register(const InstPos &instPos) {
+ CameraHandle cameraHandle{Buckets_NewHandle(Camera_BucketContainer)};
+
+ auto &cam = Camera_BucketContainer.buckets[cameraHandle.bucketIndex][cameraHandle.itemIndex];
+ new (&cam) PkeCamera{};
+
+ ECS_CreateEntity(&cam, nullptr);
+ cam.camHandle = cameraHandle;
+ cam.phys.inst = ECS_CreateInstance(&cam, nullptr);
+
+ return PkeCamera_Register_Inner(cam, instPos);
+}
+
PkeCamera *PkeCamera_Get(CameraHandle cameraHandle) {
assert(cameraHandle != CameraHandle_MAX);
return &Camera_BucketContainer.buckets[cameraHandle.bucketIndex][cameraHandle.itemIndex];
}
+PkeCamera *PkeCamera_Get(EntityHandle handle) {
+ assert(handle != EntityHandle_MAX);
+ for (PkeHandleBucketIndex_T b = 0; b <= Camera_BucketContainer.pkeHandle.bucketIndex; ++b) {
+ auto &bkt = Camera_BucketContainer.buckets[b];
+ long itemCount = Camera_BucketContainer.pkeHandle.bucketIndex == b ? Camera_BucketContainer.pkeHandle.itemIndex : Camera_BucketContainer.limits.itemIndex;
+ for (PkeHandleItemIndex_T i = 0; i < itemCount; ++i) {
+ auto &cam = bkt[i];
+ if (cam.handle == handle)
+ return &Camera_BucketContainer.buckets[cam.camHandle.bucketIndex][cam.camHandle.itemIndex];
+ }
+ }
+ return nullptr;
+}
+
void PkeCamera_AttachToInstance(CameraHandle cameraHandle, CompInstance *inst) {
assert(cameraHandle != CameraHandle_MAX);
auto &cam = Camera_BucketContainer.buckets[cameraHandle.bucketIndex][cameraHandle.itemIndex];
@@ -81,10 +97,9 @@ void PkeCamera_AttachToInstance(CameraHandle cameraHandle, CompInstance *inst) {
btTransform trfm;
inst->bt.motionState->getWorldTransform(trfm);
- BulletToGlm(trfm.getOrigin(), cam.target);
trfm.setOrigin(trfm.getOrigin() + cameraOffset);
- BulletToGlm(trfm.getOrigin(), cam.pos);
+ cam.phys.targetInst = inst;
cam.phys.inst->bt.motionState->setWorldTransform(trfm);
cam.phys.inst->bt.rigidBody->setWorldTransform(trfm);
cam.phys.inst->bt.rigidBody->setLinearVelocity(btVector3(0,0,0));
@@ -93,7 +108,7 @@ void PkeCamera_AttachToInstance(CameraHandle cameraHandle, CompInstance *inst) {
assert(cam.phys.constraint == nullptr || cam.phys.constraint == CAFE_BABE(btTypedConstraint));
cam.phys.constraint = Pke_New<btTypedConstraint>(MemBkt_Bullet);
- new (cam.phys.constraint) btPoint2PointConstraint(*cam.phys.inst->bt.rigidBody, *inst->bt.rigidBody, btVector3(0.f, 0.f, 0.f), cameraOffset);
+ new (cam.phys.constraint) btPoint2PointConstraint(*cam.phys.inst->bt.rigidBody, *inst->bt.rigidBody, btVector3(0.f, -1.f, -1.f), cameraOffset);
BtDynamicsWorld->addConstraint(cam.phys.constraint);
cam.view = PKE_CAMERA_VIEW_TARGET;
@@ -122,13 +137,11 @@ void PkeCamera_Destroy(CameraHandle cameraHandle) {
ECS_MarkForRemoval(camPtr);
cam.camHandle = CameraHandle_MAX;
- cam.pos = glm::vec3(0);
- cam.rot = glm::quat{};
- cam.target = glm::vec3(0);
cam.type = PkeCameraType_MAX;
cam.view = PkeCameraView_MAX;
cam.stale = PkeCameraStaleFlags_MAX;
cam.phys.inst = CAFE_BABE(CompInstance);
+ cam.phys.targetInst = CAFE_BABE(CompInstance);
cam.phys.constraint = CAFE_BABE(btTypedConstraint);
}
@@ -147,10 +160,23 @@ PkeCamera *PkeCamera_GetCameras(int64_t bucketIndex, int64_t &count) {
void PkeCamera_Init() {
Buckets_Init(Camera_BucketContainer, MAX_CAMERAS_PER_BUCKET);
+ NullCamera.phys.inst = Pke_New<CompInstance>();
+ InstPos instPos{
+ .scale = btVector3(1.f, 1.f, 1.f),
+ .mass = 1.f,
+ };
+ PkeCamera_Register_Inner(NullCamera, instPos);
}
void PkeCamera_Teardown() {
Buckets_Destroy(Camera_BucketContainer);
+ BtDynamicsWorld->removeRigidBody(NullCamera.phys.inst->bt.rigidBody);
+ Pke_Delete<btDefaultMotionState>(NullCamera.phys.inst->bt.motionState, MemBkt_Bullet);
+ Pke_Delete<btRigidBody>(NullCamera.phys.inst->bt.rigidBody, MemBkt_Bullet);
+ NullCamera.phys.inst->bt.motionState = CAFE_BABE(btDefaultMotionState);
+ NullCamera.phys.inst->bt.rigidBody = CAFE_BABE(btRigidBody);
+ Pke_Delete<CompInstance>(NullCamera.phys.inst);
+ NullCamera.phys.inst = CAFE_BABE(CompInstance);
}
void PkeCamera_Tick(double delta) {
@@ -172,18 +198,13 @@ void PkeCamera_Tick(double delta) {
if (cam.handle == EntityHandle_MAX) {
continue;
}
- btTransform trfm;
- if (cam.phys.constraint != nullptr && cam.phys.constraint != CAFE_BABE(btTypedConstraint)) {
- cam.phys.constraint->getRigidBodyB().getMotionState()->getWorldTransform(trfm);
- BulletToGlm(trfm.getOrigin(), cam.target);
- }
- if (cam.phys.inst != nullptr && cam.phys.inst != CAFE_BABE(CompInstance)) {
- cam.phys.inst->bt.motionState->getWorldTransform(trfm);
- BulletToGlm(trfm.getOrigin(), cam.pos);
- BulletToGlm(trfm.getRotation(), cam.rot);
+ if (cam.phys.inst != nullptr && cam.phys.inst != CAFE_BABE(CompInstance) && cam.phys.inst->isNeedingUpdated == true) {
cam.stale = cam.stale | PKE_CAMERA_STALE_POSROT;
cam.phys.inst->isNeedingUpdated = false;
}
+ if (cam.phys.targetInst != nullptr && cam.phys.targetInst != CAFE_BABE(CompInstance) && cam.phys.targetInst->isNeedingUpdated == true) {
+ cam.stale = cam.stale | PKE_CAMERA_STALE_POSROT;
+ }
}
}
}
diff --git a/src/camera.hpp b/src/camera.hpp
index 19e9da8..a2cce39 100644
--- a/src/camera.hpp
+++ b/src/camera.hpp
@@ -30,14 +30,12 @@ constexpr PkeCameraStaleFlags PKE_CAMERA_STALE_ALL = PkeCameraStaleFlags
struct PkeCamera : public Entity_Base {
CameraHandle camHandle = CameraHandle_MAX;
- glm::vec3 pos = glm::vec3(0);
- glm::quat rot = glm::quat{};
- glm::vec3 target = glm::vec3(0);
PkeCameraType type = PkeCameraType_MAX;
PkeCameraView view = PkeCameraView_MAX;
PkeCameraStaleFlags stale = PkeCameraStaleFlags_MAX;
struct Phys {
CompInstance *inst = nullptr;
+ CompInstance *targetInst = nullptr;
btTypedConstraint *constraint = nullptr;
} phys;
bool isPrimary = false;
@@ -48,6 +46,7 @@ extern PkeCamera *ActiveCamera;
void PkeCamera_Init();
PkeCamera &PkeCamera_Register(const InstPos &instPos);
PkeCamera *PkeCamera_Get(CameraHandle handle);
+PkeCamera *PkeCamera_Get(EntityHandle handle);
void PkeCamera_AttachToInstance(CameraHandle cameraHandle, CompInstance *inst);
void PkeCamera_DetachFromInstance(CameraHandle cameraHandle, CompInstance *inst);
int64_t PkeCamera_GetBucketCount();
diff --git a/src/components.hpp b/src/components.hpp
index 60b4c8e..7d298ec 100644
--- a/src/components.hpp
+++ b/src/components.hpp
@@ -4,7 +4,7 @@
#include "dynamic-array.hpp"
#include "macros.hpp"
#include "physics.hpp"
-#include "plugins.hpp"
+#include "plugin-types.hpp"
#include <BulletDynamics/Dynamics/btRigidBody.h>
#include <LinearMath/btDefaultMotionState.h>
@@ -74,8 +74,8 @@ struct InstPos {
btScalar mass;
};
struct InstBt {
- btDefaultMotionState *motionState;
- btRigidBody *rigidBody;
+ btDefaultMotionState *motionState = nullptr;
+ btRigidBody *rigidBody = nullptr;
};
struct CompInstance {
EntityHandle entHandle = EntityHandle_MAX;
diff --git a/src/entities.cpp b/src/entities.cpp
index be0286c..cb66cef 100644
--- a/src/entities.cpp
+++ b/src/entities.cpp
@@ -8,6 +8,7 @@
#include "math-helpers.hpp"
#include "memory.hpp"
#include "physics.hpp"
+#include "plugins.hpp"
#include "static/missing-texture.hpp"
#include "window.hpp"
diff --git a/src/game.cpp b/src/game.cpp
index 4390202..565f1ce 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -1,9 +1,11 @@
#include "game.hpp"
+#include "array.hpp"
#include "camera.hpp"
#include "components.hpp"
#include "dynamic-array.hpp"
+#include "ecs.hpp"
#include "entities.hpp"
#include "game-settings.hpp"
#include "helpers.hpp"
@@ -32,6 +34,13 @@
const long readLineLength = 128;
char readLine[readLineLength];
+struct InstMapping {
+ InstanceHandle origHandle = InstanceHandle_MAX;
+ Entity_Base *newEnt = nullptr;
+ CompInstance *newInst = nullptr;
+ InstPos newInstance{};
+};
+PkeArray<InstMapping> loadFileInstanceMappings{};
const char *levelName = "demo-level";
@@ -42,6 +51,7 @@ const char *PKE_FILE_OBJ_END = "";
const char *PKE_FILE_OBJ_INSTANCE = "Instance:";
const char *PKE_FILE_OBJ_CAMERA = "Camera:";
+const char *PKE_FILE_INSTANCE_HANDLE = "Inst::InstHandle: ";
const char *PKE_FILE_INSTANCE_ENTITY_HANDLE = "EntityHandle: ";
const char *PKE_FILE_INSTANCE_ENTITY_TYPE_CODE = "EntityTypeCode: ";
const char *PKE_FILE_INSTANCE_POS_POS = "InstPos::Pos: ";
@@ -52,61 +62,64 @@ const char *PKE_FILE_INSTANCE_PHYSICS_COLLISION_LAYER = "InstPos::CollisionLayer
const char *PKE_FILE_INSTANCE_PHYSICS_COLLISION_MASK = "InstPos::CollisionMask: ";
const char *PKE_FILE_INSTANCE_COLLISION_CALLBACK_SIGNATURE = "Inst::CollisionCallbackSignature: ";
+const char PKE_FILE_INSTANCE_SPECIAL_ENTITY_TYPE_CODE_CAMERA = 'C';
+
const char *PKE_FILE_CAMERA_POS = "Cam::Pos: ";
const char *PKE_FILE_CAMERA_ROT = "Cam::Rot: ";
const char *PKE_FILE_CAMERA_TARGET = "Cam::Target: ";
const char *PKE_FILE_CAMERA_TYPE = "Cam::Type: ";
const char *PKE_FILE_CAMERA_ORIENTATION = "Cam::Orientation: ";
+const char *PKE_FILE_CAMERA_INSTANCE_HANDLE = "Cam::InstanceHandle: ";
+const char *PKE_FILE_CAMERA_TARGET_INSTANCE_HANDLE = "Cam::TargetInstanceHandle: ";
const char *PKE_FILE_CAMERA_IS_PRIMARY = "Cam::IsPrimary: ";
void SerializeCamera(std::ostringstream &stream, const PkeCamera &cam) {
+ NULL_CHAR_ARR(handleStr, 19);
PkeCamera c{};
- if (cam.pos != c.pos) {
- stream << PKE_FILE_CAMERA_POS << "["
- << std::setw(10) << cam.pos[0] << ","
- << std::setw(10) << cam.pos[1] << ","
- << std::setw(10) << cam.pos[2] << "]" << std::endl;
- }
- if (cam.rot != c.rot) {
- stream << PKE_FILE_CAMERA_ROT << "["
- << std::setw(10) << cam.rot[0] << ","
- << std::setw(10) << cam.rot[1] << ","
- << std::setw(10) << cam.rot[2] << ","
- << std::setw(10) << cam.rot[3] << "]" << std::endl;
- }
- if (cam.target != c.target) {
- stream << PKE_FILE_CAMERA_TARGET << "["
- << std::setw(10) << cam.target[0] << ","
- << std::setw(10) << cam.target[1] << ","
- << std::setw(10) << cam.target[2] << "]" << std::endl;
- }
if (cam.type != c.type) {
stream << PKE_FILE_CAMERA_TYPE << int(static_cast<PkeCameraType_T>(cam.type)) << std::endl;
}
if (cam.view != c.view) {
stream << PKE_FILE_CAMERA_ORIENTATION << int(static_cast<PkeCameraView_T>(cam.view)) << std::endl;
}
+ if (cam.phys.inst != c.phys.inst && cam.phys.inst != CAFE_BABE(CompInstance)) {
+ snprintf(handleStr, 19, "0x%016lX", cam.phys.inst->instanceHandle.hash);
+ stream << PKE_FILE_CAMERA_INSTANCE_HANDLE << handleStr << std::endl;
+ }
+ if (cam.phys.targetInst != c.phys.targetInst && cam.phys.targetInst != CAFE_BABE(CompInstance)) {
+ snprintf(handleStr, 19, "0x%016lX", cam.phys.targetInst->instanceHandle.hash);
+ stream << PKE_FILE_CAMERA_TARGET_INSTANCE_HANDLE << handleStr << std::endl;
+ }
if (cam.isPrimary != c.isPrimary) {
stream << PKE_FILE_CAMERA_IS_PRIMARY << cam.isPrimary << std::endl;
}
}
void SerializeInstance(std::ostringstream &stream, const CompInstance &comp) {
- char handleStr[19] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' };
- snprintf(handleStr, 19, "0x%016lX", comp.entHandle.hash);
- assert(comp.grBindsHandle != GrBindsHandle_MAX && "instance exists without a GrBinds");
- CompGrBinds *instGrBinds = ECS_GetGrBinds(comp.grBindsHandle);
- EntityType *et = EntityType_FindByEntityHandle(instGrBinds->entHandle);
- assert(et != nullptr && "instance had a GrBinds, but no EntityType could be found");
+ NULL_CHAR_ARR(handleStr, 19);
+ EntityType *et = nullptr;
+ if (comp.grBindsHandle != GrBindsHandle_MAX) {
+ et = EntityType_FindByEntityHandle(ECS_GetGrBinds(comp.grBindsHandle)->entHandle);
+ }
CompInstance c{};
InstPos baseInst{};
baseInst.posRot = btTransform{};
baseInst.posRot.setIdentity();
baseInst.scale = btVector3(1, 1, 1);
baseInst.mass = 1;
- if (comp.entHandle != c.entHandle)
+ if (comp.entHandle != c.entHandle) {
+ snprintf(handleStr, 19, "0x%016lX", comp.entHandle.hash);
stream << PKE_FILE_INSTANCE_ENTITY_HANDLE << handleStr << std::endl;
- stream << PKE_FILE_INSTANCE_ENTITY_TYPE_CODE << et->entityTypeCode << std::endl;
+ }
+ if (comp.entHandle != c.entHandle) {
+ snprintf(handleStr, 19, "0x%016lX", comp.instanceHandle.hash);
+ stream << PKE_FILE_INSTANCE_HANDLE << handleStr << std::endl;
+ }
+ if (et != nullptr) {
+ stream << PKE_FILE_INSTANCE_ENTITY_TYPE_CODE << et->entityTypeCode << std::endl;
+ } else if (PkeCamera_Get(comp.entHandle)) {
+ stream << PKE_FILE_INSTANCE_ENTITY_TYPE_CODE << PKE_FILE_INSTANCE_SPECIAL_ENTITY_TYPE_CODE_CAMERA << std::endl;
+ }
btTransform trans;
comp.bt.motionState->getWorldTransform(trans);
@@ -146,71 +159,46 @@ void SerializeInstance(std::ostringstream &stream, const CompInstance &comp) {
}
}
+bool FindFirstInstanceHandle(const InstMapping &mapping, const InstanceHandle handle) {
+ return mapping.origHandle == handle;
+}
void ParseCamera(PkeLevel *level, std::ifstream &stream) {
PkeCamera cam{};
+ InstanceHandle instanceHandle = InstanceHandle_MAX;
+ InstanceHandle targetInstanceHandle = InstanceHandle_MAX;
while (stream.getline(readLine, readLineLength)) {
if (strcmp(readLine, PKE_FILE_OBJ_END) == 0) {
- InstPos instPos{};
- btVector3 pos;
- btQuaternion quat;
- GlmToBullet(cam.pos, pos);
- GlmToBullet(cam.rot, quat);
- instPos.mass = 1.f;
- instPos.posRot.setOrigin(pos);
- instPos.posRot.setRotation(quat);
+
+ int64_t instanceIndex = -1, targetInstanceIndex = -1;
+
+ instanceIndex = PkeArray_FindFirstIndex<InstMapping, InstanceHandle>(&loadFileInstanceMappings, FindFirstInstanceHandle, instanceHandle);
+
+ if (targetInstanceHandle != InstanceHandle_MAX) {
+ targetInstanceIndex = PkeArray_FindFirstIndex<InstMapping, InstanceHandle>(&loadFileInstanceMappings, FindFirstInstanceHandle, targetInstanceHandle);
+ }
+
+ InstPos instPos;
+ if (instanceIndex == -1) {
+ instPos.mass = 1.f;
+ instPos.posRot.setIdentity();
+ instPos.scale = btVector3(1.f, 1.f, 1.f);
+ fprintf(stdout, "[ParseCamera] Failed to find instance mapping. Is this an outdated parse?");
+ } else {
+ instPos = loadFileInstanceMappings.data[instanceIndex].newInstance;
+ }
auto &rCam = PkeCamera_Register(instPos);
- rCam.target = cam.target;
rCam.type = cam.type;
rCam.view = cam.view;
rCam.isPrimary = cam.isPrimary;
PkeLevel_RegisterCamera(level->levelHandle, rCam.camHandle);
+ if (targetInstanceIndex > -1) {
+ PkeCamera_AttachToInstance(rCam.camHandle, loadFileInstanceMappings.data[targetInstanceIndex].newInst);
+ }
if (rCam.isPrimary == true) {
ActiveCamera = &rCam;
}
return;
}
- if (strncmp(readLine, PKE_FILE_CAMERA_POS, strlen(PKE_FILE_CAMERA_POS)) == 0) {
- uint64_t prefixLen = strlen(PKE_FILE_CAMERA_POS);
- char *startingChar = strchr(readLine + prefixLen, '[') + 1;
- assert(startingChar != nullptr);
- char *pEnd = nullptr;
- long index = 0;
- do {
- assert(index < 3);
- STR2NUM_ERROR result = str2num(cam.pos[index], startingChar, pEnd);
- assert(result == STR2NUM_ERROR::SUCCESS);
- startingChar = pEnd + 1;
- ++index;
- } while (*pEnd != ']');
- }
- if (strncmp(readLine, PKE_FILE_CAMERA_ROT, strlen(PKE_FILE_CAMERA_ROT)) == 0) {
- uint64_t prefixLen = strlen(PKE_FILE_CAMERA_ROT);
- char *startingChar = strchr(readLine + prefixLen, '[') + 1;
- assert(startingChar != nullptr);
- char *pEnd = nullptr;
- long index = 0;
- do {
- assert(index < 4);
- STR2NUM_ERROR result = str2num(cam.rot[index], startingChar, pEnd);
- assert(result == STR2NUM_ERROR::SUCCESS);
- startingChar = pEnd + 1;
- ++index;
- } while (*pEnd != ']');
- }
- if (strncmp(readLine, PKE_FILE_CAMERA_TARGET, strlen(PKE_FILE_CAMERA_TARGET)) == 0) {
- uint64_t prefixLen = strlen(PKE_FILE_CAMERA_TARGET);
- char *startingChar = strchr(readLine + prefixLen, '[') + 1;
- assert(startingChar != nullptr);
- char *pEnd = nullptr;
- long index = 0;
- do {
- assert(index < 3);
- STR2NUM_ERROR result = str2num(cam.target[index], startingChar, pEnd);
- assert(result == STR2NUM_ERROR::SUCCESS);
- startingChar = pEnd + 1;
- ++index;
- } while (*pEnd != ']');
- }
if (strncmp(readLine, PKE_FILE_CAMERA_TYPE, strlen(PKE_FILE_CAMERA_TYPE)) == 0) {
uint64_t prefixLen = strlen(PKE_FILE_CAMERA_TYPE);
PkeCameraType_T handle_t;
@@ -227,6 +215,18 @@ void ParseCamera(PkeLevel *level, std::ifstream &stream) {
cam.view = PkeCameraView{handle_t};
continue;
}
+ if (strstr(readLine, PKE_FILE_CAMERA_INSTANCE_HANDLE)) {
+ uint64_t prefixLen = strlen(PKE_FILE_CAMERA_INSTANCE_HANDLE);
+ STR2NUM_ERROR result = str2num(instanceHandle.hash, readLine + prefixLen);
+ assert(result == STR2NUM_ERROR::SUCCESS);
+ continue;
+ }
+ if (strstr(readLine, PKE_FILE_CAMERA_TARGET_INSTANCE_HANDLE)) {
+ uint64_t prefixLen = strlen(PKE_FILE_CAMERA_TARGET_INSTANCE_HANDLE);
+ STR2NUM_ERROR result = str2num(targetInstanceHandle.hash, readLine + prefixLen);
+ assert(result == STR2NUM_ERROR::SUCCESS);
+ continue;
+ }
if (strncmp(readLine, PKE_FILE_CAMERA_IS_PRIMARY, strlen(PKE_FILE_CAMERA_IS_PRIMARY)) == 0) {
uint64_t prefixLen = strlen(PKE_FILE_CAMERA_IS_PRIMARY);
uint8_t isPrimary;
@@ -240,31 +240,53 @@ void ParseCamera(PkeLevel *level, std::ifstream &stream) {
void ParseInstance(Entity_Base *parentEntity, std::ifstream &stream) {
CompInstance comp{};
- InstPos instPos{};
- instPos.posRot = btTransform{};
- instPos.posRot.setIdentity();
- instPos.scale = btVector3(1, 1, 1);
- instPos.mass = 1.f;
+ InstMapping mapping {
+ .origHandle = InstanceHandle_MAX,
+ .newInstance = {
+ .scale = btVector3(1.f, 1.f, 1.f),
+ .mass = 1.f,
+ },
+ };
+ mapping.newInstance.posRot.setIdentity();
comp.collisionCallback.name[0] = '\0';
NULL_CHAR_ARR(entTypeCode, 21);
while (stream.getline(readLine, readLineLength)) {
if (strstr(PKE_FILE_OBJ_END, readLine)) {
- if (entTypeCode[0] == '\0') {
+ EntityType *etPtr = nullptr;
+ bool skipEntCreate = false;
+ if (strlen(entTypeCode) > 1) {
+ etPtr = EntityType_FindByTypeCode(entTypeCode);
+ if (etPtr == nullptr) {
+ fprintf(stdout, "[Game::ParseInstance] Unknown EntityTypeCode: \"%s\"\n", entTypeCode);
+ break;
+ }
+ } else if (strlen(entTypeCode) == 1) {
+ // handle internally
+ if (entTypeCode[0] == PKE_FILE_INSTANCE_SPECIAL_ENTITY_TYPE_CODE_CAMERA) {
+ skipEntCreate = true;
+ }
+ } else {
fprintf(stdout, "[Game::ParseInstance] Failed to create instance from save file. No EntTypeCode present.\n");
break;
}
- auto *etPtr = EntityType_FindByTypeCode(entTypeCode);
- if (etPtr == nullptr) {
- fprintf(stdout, "[Game::ParseInstance] Failed to create instance from save file. Unknown EntityTypeCode: \"%s\"\n", entTypeCode);
- break;
- }
- if (etPtr->createInstanceCallback.func != nullptr) {
- reinterpret_cast<void(*)()>(etPtr->createInstanceCallback.func)();
- } else {
- EntityType_CreateGenericInstance(etPtr, parentEntity, &comp, &instPos);
- fprintf(stdout ,"[Game::ParseInstance] No callback func to create instance.");
+ if (skipEntCreate == false) {
+ if (etPtr != nullptr && etPtr->createInstanceCallback.func != nullptr) {
+ typedef Entity_Base *CreateInst();
+ mapping.newEnt = reinterpret_cast<CreateInst*>(etPtr->createInstanceCallback.func)();
+ } else {
+ mapping.newEnt = EntityType_CreateGenericInstance(etPtr, parentEntity, &comp, &mapping.newInstance);
+ fprintf(stdout ,"[Game::ParseInstance] No callback func to create instance.");
+ }
}
+ if (mapping.newEnt != nullptr) {
+ // TODO this is messy
+ PkeArray<CompInstance *> instances{};
+ ECS_GetInstances(mapping.newEnt, instances);
+ assert(instances.next > 0);
+ mapping.newInst = instances.data[0];
+ }
+ PkeArray_Add(&loadFileInstanceMappings, mapping);
break;
}
if (strstr(readLine, PKE_FILE_INSTANCE_ENTITY_HANDLE)) {
@@ -273,6 +295,12 @@ void ParseInstance(Entity_Base *parentEntity, std::ifstream &stream) {
assert(result == STR2NUM_ERROR::SUCCESS);
continue;
}
+ if (strstr(readLine, PKE_FILE_INSTANCE_HANDLE)) {
+ uint64_t prefixLen = strlen(PKE_FILE_INSTANCE_HANDLE);
+ STR2NUM_ERROR result = str2num(mapping.origHandle.hash, readLine + prefixLen);
+ assert(result == STR2NUM_ERROR::SUCCESS);
+ continue;
+ }
if (strstr(readLine, PKE_FILE_INSTANCE_ENTITY_TYPE_CODE)) {
uint64_t prefixLen = strlen(PKE_FILE_INSTANCE_ENTITY_TYPE_CODE);
strncpy(entTypeCode, readLine + prefixLen, 21);
@@ -292,7 +320,7 @@ void ParseInstance(Entity_Base *parentEntity, std::ifstream &stream) {
startingChar = pEnd + 1;
++index;
} while (*pEnd != ']');
- instPos.posRot.setOrigin(pos);
+ mapping.newInstance.posRot.setOrigin(pos);
continue;
}
if (strstr(readLine, PKE_FILE_INSTANCE_POS_ROT)) {
@@ -309,7 +337,7 @@ void ParseInstance(Entity_Base *parentEntity, std::ifstream &stream) {
startingChar = pEnd + 1;
++index;
} while (*pEnd != ']');
- instPos.posRot.setRotation(rot);
+ mapping.newInstance.posRot.setRotation(rot);
continue;
}
if (strstr(readLine, PKE_FILE_INSTANCE_POS_SCALE)) {
@@ -320,7 +348,7 @@ void ParseInstance(Entity_Base *parentEntity, std::ifstream &stream) {
long index = 0;
do {
assert(index < 3);
- STR2NUM_ERROR result = str2num(instPos.scale[index], startingChar, pEnd);
+ STR2NUM_ERROR result = str2num(mapping.newInstance.scale[index], startingChar, pEnd);
assert(result == STR2NUM_ERROR::SUCCESS);
startingChar = pEnd + 1;
++index;
@@ -329,7 +357,7 @@ void ParseInstance(Entity_Base *parentEntity, std::ifstream &stream) {
}
if (strstr(readLine, PKE_FILE_INSTANCE_PHYSICS_MASS)) {
uint64_t prefixLen = strlen(PKE_FILE_INSTANCE_PHYSICS_MASS);
- STR2NUM_ERROR result = str2num(instPos.mass, readLine + prefixLen);
+ STR2NUM_ERROR result = str2num(mapping.newInstance.mass, readLine + prefixLen);
assert(result == STR2NUM_ERROR::SUCCESS);
continue;
}
@@ -366,20 +394,6 @@ void Game_SaveSceneFile(const char *sceneFilePath) {
stream << PKE_FILE_VERSION << std::endl;
stream << "" << std::endl;
- int64_t cameraBucketCount = PkeCamera_GetBucketCount();
- for (long b = 0; b < cameraBucketCount; ++b) {
- int64_t count;
- auto *cameras = PkeCamera_GetCameras(b, count);
- for (long i = 0; i < count; ++i) {
- const auto &cam = cameras[i];
- if (cam.handle == CameraHandle_MAX)
- continue;
- stream << PKE_FILE_OBJ_CAMERA << std::endl;
- SerializeCamera(stream, cam);
- stream << PKE_FILE_OBJ_END << std::endl;
- }
- }
-
int64_t instanceBucketCount = ECS_GetInstances_BucketCount();
for (long b = 0; b < instanceBucketCount; ++b) {
uint64_t count;
@@ -388,23 +402,26 @@ void Game_SaveSceneFile(const char *sceneFilePath) {
const auto &instance = instances[i];
if (instance.entHandle == EntityHandle_MAX)
continue;
- /* 2024-01-16 - JCB - TODO Checking the GRBinds is currently
- * set so that we don't serialize cameras. There's probably
- * a better way to do this - or cameras should be refactored
- * to rely on the instance position?
- * I expect this to become an issue later, but I'm not aware
- * of any use-cases at the moment. Leaving this as-is until
- * we know what those use-cases are so we can write a valid
- * story to handle the task.
- */
- if (instance.grBindsHandle == GrBindsHandle_MAX)
- continue;
stream << PKE_FILE_OBJ_INSTANCE << std::endl;
SerializeInstance(stream, instance);
stream << PKE_FILE_OBJ_END << std::endl;
}
}
+ int64_t cameraBucketCount = PkeCamera_GetBucketCount();
+ for (long b = 0; b < cameraBucketCount; ++b) {
+ int64_t count;
+ auto *cameras = PkeCamera_GetCameras(b, count);
+ for (long i = 0; i < count; ++i) {
+ const auto &cam = cameras[i];
+ if (cam.handle == CameraHandle_MAX)
+ continue;
+ stream << PKE_FILE_OBJ_CAMERA << std::endl;
+ SerializeCamera(stream, cam);
+ stream << PKE_FILE_OBJ_END << std::endl;
+ }
+ }
+
stream << PKE_FILE_END << std::endl;
}
catch (...) {
@@ -448,17 +465,18 @@ void Game_LoadSceneFile(PkeLevel *level, const char *sceneFilePath) {
memset(readLine, '\0', readLineLength);
while (f.getline(readLine, readLineLength)) {
- if (strcmp(PKE_FILE_OBJ_CAMERA, readLine) == 0) {
- ParseCamera(level, f);
- continue;
- }
if (strcmp(PKE_FILE_OBJ_INSTANCE, readLine) == 0) {
ParseInstance(level, f);
continue;
}
+ if (strcmp(PKE_FILE_OBJ_CAMERA, readLine) == 0) {
+ ParseCamera(level, f);
+ continue;
+ }
}
f.close();
+ PkeArray_SoftReset(&loadFileInstanceMappings);
}
const uint64_t consoleBufferCount = 30;
@@ -665,12 +683,12 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) {
Event_Teardown();
EntityType_Teardown();
PkeInput_Teardown();
+ PkeCamera_Teardown();
Physics_Teardown();
ECS_Teardown();
- PkeCamera_Teardown();
+ DestroyWindow();
AM_DebugPrint();
AM_Teardown();
- DestroyWindow();
PkeThreads_Teardown();
Pke_DebugPrint();
fprintf(stdout, "Game_Main Exiting\n");
diff --git a/src/plugin-types.hpp b/src/plugin-types.hpp
new file mode 100644
index 0000000..22f9707
--- /dev/null
+++ b/src/plugin-types.hpp
@@ -0,0 +1,25 @@
+#ifndef PKE_PLUGIN_TYPES_HPP
+#define PKE_PLUGIN_TYPES_HPP
+
+#include <cstdint>
+
+struct PKEPluginInterface {
+ // for internal use only
+ void *pluginHandle = nullptr;
+ void (*OnInit)() = nullptr;
+ void (*OnTick)(double delta) = nullptr;
+ void (*OnTeardown)() = nullptr;
+ void (*OnImGuiRender)() = nullptr;
+};
+
+constexpr int64_t CallbackSignatureLength = 16;
+using CallbackSignature = char[CallbackSignatureLength];
+
+struct PkeCallback {
+ // the 16 char signature(name) of a function
+ CallbackSignature name = {'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'};
+ // the address of the function to call - populated on startup
+ void *func = nullptr;
+};
+
+#endif /* PKE_PLUGIN_TYPES_HPP */
diff --git a/src/plugins.hpp b/src/plugins.hpp
index a474750..697fbf1 100644
--- a/src/plugins.hpp
+++ b/src/plugins.hpp
@@ -3,24 +3,7 @@
#include "array.hpp"
#include "dynamic-array.hpp"
-
-struct PKEPluginInterface {
- // for internal use only
- void *pluginHandle = nullptr;
- void (*OnInit)() = nullptr;
- void (*OnTick)(double delta) = nullptr;
- void (*OnTeardown)() = nullptr;
- void (*OnImGuiRender)() = nullptr;
-};
-
-constexpr int64_t CallbackSignatureLength = 16;
-using CallbackSignature = char[CallbackSignatureLength];
-struct PkeCallback {
- // the 16 char signature(name) of a function
- CallbackSignature name = {'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'};
- // the address of the function to call - populated on startup
- void *func = nullptr;
-};
+#include "plugin-types.hpp"
extern DynArray<PKEPluginInterface> LoadedPkePlugins;
extern PkeArray<PkeCallback> pkePluginCallbacks;
diff --git a/src/project.cpp b/src/project.cpp
index 0f08859..4412522 100644
--- a/src/project.cpp
+++ b/src/project.cpp
@@ -1,6 +1,7 @@
#include "project.hpp"
+#include "plugins.hpp"
#include "entities.hpp"
#include "helpers.hpp"
diff --git a/src/window.cpp b/src/window.cpp
index 1d27664..db817e6 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -1,3 +1,4 @@
+#include "math-helpers.hpp"
#include "static/missing-texture.hpp"
#define GLFW_INCLUDE_NONE
#define GLFW_INCLUDE_VULKAN
@@ -907,14 +908,27 @@ void UpdatePresentDescriptorSets() {
}
void UpdateCamera() {
+ if (ActiveCamera->stale == PkeCameraStaleFlags{0}) return;
+ glm::vec3 gPos;
+ glm::quat gRot;
+ btTransform trfm;
+ ActiveCamera->phys.inst->bt.motionState->getWorldTransform(trfm);
+ BulletToGlm(trfm.getOrigin(), gPos);
+ BulletToGlm(trfm.getRotation(), gRot);
if (bool(ActiveCamera->stale & PKE_CAMERA_STALE_POS)) {
- UBO.model = glm::translate(glm::mat4(1.f), ActiveCamera->pos);
+ UBO.model = glm::translate(glm::mat4(1.f), gPos);
}
if (bool(ActiveCamera->stale & PKE_CAMERA_STALE_ROT)) {
if (bool(ActiveCamera->view == PKE_CAMERA_VIEW_FREE)) {
- UBO.view = glm::mat4_cast(ActiveCamera->rot);
+ UBO.view = glm::mat4_cast(gRot);
} else if (bool(ActiveCamera->view == PKE_CAMERA_VIEW_TARGET)) {
- UBO.view = glm::lookAt(glm::vec3(0), ActiveCamera->pos - ActiveCamera->target, glm::vec3(0.f, 1.f, 0.f));
+ glm::vec3 gTargetPos{0.f, 0.f, 0.f};
+ if (ActiveCamera->phys.targetInst != nullptr && ActiveCamera->phys.targetInst != CAFE_BABE(CompInstance)) {
+ btTransform targetTrfm;
+ ActiveCamera->phys.targetInst->bt.motionState->getWorldTransform(targetTrfm);
+ BulletToGlm(trfm.getOrigin(), gTargetPos);
+ }
+ UBO.view = glm::lookAt(glm::vec3(0), gPos - gTargetPos, glm::vec3(0.f, 1.f, 0.f));
}
}
if (bool(ActiveCamera->stale & PKE_CAMERA_STALE_PERSPECTIVE)) {