summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-01-14 15:50:04 -0500
committerJonathan Bradley <jcb@pikum.xyz>2025-01-14 15:50:04 -0500
commit80a67230fe192287503092a3d256aea3a494409c (patch)
tree187f2e7a41e0cd206d9969284a3abce4028d89f5
parent46d814de510d0a7753c3e49eed3b3440d1c7c681 (diff)
pke: camera can track a given target
-rw-r--r--editor/editor.cpp96
-rw-r--r--src/camera.cpp114
-rw-r--r--src/camera.hpp9
-rw-r--r--src/entities.cpp16
-rw-r--r--src/game.cpp33
-rw-r--r--src/window.cpp18
6 files changed, 188 insertions, 98 deletions
diff --git a/editor/editor.cpp b/editor/editor.cpp
index 024e855..2bcca0a 100644
--- a/editor/editor.cpp
+++ b/editor/editor.cpp
@@ -288,11 +288,12 @@ void PkeEditor_Tick(double delta) {
selectedCamera = CameraHandle_MAX;
if (ActiveCamera != &NullCamera) {
btTransform btfm;
- ActiveCamera->phys.inst->bt.motionState->getWorldTransform(btfm);
- NullCamera.phys.inst->bt.motionState->setWorldTransform(btfm);
- NullCamera.phys.inst->bt.rigidBody->setWorldTransform(btfm);
- NullCamera.phys.inst->bt.rigidBody->activate();
- NullCamera.phys.targetInst = ActiveCamera->phys.targetInst;
+ CompInstance *inst = ECS_GetInstance(ActiveCamera->phys.instHandle);
+ inst->bt.motionState->getWorldTransform(btfm);
+ NullCameraInstance.bt.motionState->setWorldTransform(btfm);
+ NullCameraInstance.bt.rigidBody->setWorldTransform(btfm);
+ NullCameraInstance.bt.rigidBody->activate();
+ NullCamera.phys.targetInstHandle = ActiveCamera->phys.targetInstHandle;
NullCamera.type = ActiveCamera->type;
NullCamera.view = ActiveCamera->view;
NullCamera.stale = PKE_CAMERA_STALE_ALL;
@@ -309,7 +310,7 @@ void PkeEditor_Tick(double delta) {
holder = PkeInput_Query(dbgCtrl_CameraRot);
btTransform trfm;
- NullCamera.phys.inst->bt.motionState->getWorldTransform(trfm);
+ NullCameraInstance.bt.motionState->getWorldTransform(trfm);
if (holder.type != InputEventHash{0}) {
const PkeCursorPosEvent *posEvent = static_cast<PkeCursorPosEvent *>(holder.ptr);
@@ -426,9 +427,9 @@ void PkeEditor_Tick(double delta) {
NullCamera.stale = NullCamera.stale | PKE_CAMERA_STALE_ROT;
}
- NullCamera.phys.inst->bt.motionState->setWorldTransform(trfm);
- NullCamera.phys.inst->bt.rigidBody->setWorldTransform(trfm);
- NullCamera.phys.inst->bt.rigidBody->activate();
+ NullCameraInstance.bt.motionState->setWorldTransform(trfm);
+ NullCameraInstance.bt.rigidBody->setWorldTransform(trfm);
+ NullCameraInstance.bt.rigidBody->activate();
}
holder = PkeInput_Query(dbgCtrl_DeleteSelectedItem);
@@ -700,17 +701,21 @@ void RecordImGuiEntityTypes() {
}
void RecordImGuiCameras() {
+ CompInstance *activeInst = nullptr;
+ CompInstance *activeTargetInst = nullptr;
if (!ImGui::Begin("Cameras")) {
ImGui::End();
return;
}
+ activeInst = ECS_GetInstance(ActiveCamera->phys.instHandle);
+ activeTargetInst = ECS_GetInstance(ActiveCamera->phys.targetInstHandle);
if (ImGui::Button("Create")) {
InstPos instPos{};
instPos.mass = 1.f;
- ActiveCamera->phys.inst->bt.motionState->getWorldTransform(instPos.posRot);
- instPos.scale = ActiveCamera->phys.inst->bt.rigidBody->getCollisionShape()->getLocalScaling();
+ activeInst->bt.motionState->getWorldTransform(instPos.posRot);
+ instPos.scale = activeInst->bt.rigidBody->getCollisionShape()->getLocalScaling();
auto &cam = PkeCamera_Register(instPos);
- cam.phys.targetInst = ActiveCamera->phys.targetInst;
+ cam.phys.targetInstHandle = ActiveCamera->phys.targetInstHandle;
cam.type = ActiveCamera->type;
cam.view = ActiveCamera->view;
cam.isPrimary = false;
@@ -752,17 +757,13 @@ void RecordImGuiCameras() {
}
ImGui::SameLine();
if (ImGui::Button("Select")) {
- selectedEntity = cam.phys.inst;
+ selectedEntity = ECS_GetInstance(cam.phys.instHandle);
}
ImGui::EndDisabled();
ImGui::TableSetColumnIndex(1);
ImGui::Text("0x%08X 0x%08X", cam.handle.bucketIndex, cam.handle.itemIndex);
ImGui::TableSetColumnIndex(2);
- if (cam.phys.targetInst != nullptr) {
- ImGui::Text("0x%08X 0x%08X", cam.phys.targetInst->entHandle.bucketIndex, cam.phys.targetInst->entHandle.itemIndex);
- } else {
- ImGui::Text("0x%p", cam.phys.targetInst);
- }
+ ImGui::Text("0x%08X 0x%08X", cam.phys.targetInstHandle.bucketIndex, cam.phys.targetInstHandle.itemIndex);
ImGui::TableSetColumnIndex(3);
ImGui::Text("%hhu", (unsigned char)cam.type);
ImGui::TableSetColumnIndex(4);
@@ -775,9 +776,10 @@ void RecordImGuiCameras() {
if (ImGui::Button("Update Position")) {
InstPos instPos{};
instPos.mass = 1.f;
- ActiveCamera->phys.inst->bt.motionState->getWorldTransform(instPos.posRot);
- instPos.scale = ActiveCamera->phys.inst->bt.rigidBody->getCollisionShape()->getLocalScaling();
- ECS_UpdateInstance(cam.phys.inst, instPos, true);
+ activeInst->bt.motionState->getWorldTransform(instPos.posRot);
+ instPos.scale = activeInst->bt.rigidBody->getCollisionShape()->getLocalScaling();
+ CompInstance *camInst = ECS_GetInstance(cam.phys.instHandle);
+ ECS_UpdateInstance(camInst, instPos, true);
}
ImGui::SameLine();
if (ImGui::Button("Make Primary")) {
@@ -1118,11 +1120,13 @@ void RecordImGui_CompInstPos(bool readonly, CompInstance *component) {
ImGui::InputScalar("Phys - Rigid Body", ImGuiDataType_U64, &component->bt.rigidBody, nullptr, nullptr, "0x%016lX", ImGuiInputTextFlags_ReadOnly);
ImGui::InputScalar("Phys - Motion State", ImGuiDataType_U64, &component->bt.motionState, nullptr, nullptr, "0x%016lX", ImGuiInputTextFlags_ReadOnly);
- // exclude EntityHandle_MAX so you can't attach the NullCamera
- ImGui::BeginDisabled(ActiveCamera->handle == component->entHandle || ActiveCamera->handle == EntityHandle_MAX || ActiveCamera->phys.inst == nullptr || ActiveCamera->phys.inst == CAFE_BABE(CompInstance) || PkeCamera_Get(selectedEntity->entHandle) != nullptr);
- if (ImGui::Button("Attach Active Camera")) {
- PkeCamera_AttachToInstance(ActiveCamera->camHandle, component);
+ // exclude EntityHandle_MAX so you can't target via the NullCamera
+ ImGui::BeginDisabled(ActiveCamera->handle == component->entHandle || ActiveCamera->handle == EntityHandle_MAX || ActiveCamera->phys.instHandle == InstanceHandle_MAX || PkeCamera_Get(selectedEntity->entHandle) != nullptr);
+ if (ImGui::Button("Set Active Camera Target")) {
+ PkeCamera_TargetInstance(ActiveCamera->camHandle, component);
}
+ ImGui::SameLine();
+ ImGui::Text("Active Camera: 0x%08X 0x%08X", ActiveCamera->handle.bucketIndex, ActiveCamera->handle.itemIndex);
ImGui::EndDisabled();
if (changed) {
@@ -1251,6 +1255,32 @@ void RecordImGuiProjectBrowser() {
ImGui::End();
}
+void RecordImGuiSceneBrowser() {
+ NULL_CHAR_ARR(text, 128);
+ CompInstance *instances;
+ EntityType *entType;
+ uint64_t i, k;
+ uint64_t bucketCount, itemCount;
+ if (!ImGui::Begin("SceneBrowser", &pkeSettings.editorSettings.isShowingSceneEditor)) {
+ ImGui::End();
+ return;
+ }
+
+ bucketCount = ECS_GetInstances_BucketCount();
+ for (i = 0; i < bucketCount; ++i) {
+ instances = ECS_GetInstances(0, itemCount);
+ for (k = 0; k < itemCount; ++k) {
+ entType = EntityType_FindByEntityHandle(instances[k].entHandle);
+ sprintf(text, "%s: %08x %08x", entType != nullptr ? entType->entityTypeCode.val : "(no type)", instances[k].instanceHandle.bucketIndex, instances[k].instanceHandle.itemIndex);
+ if (ImGui::Button(text)) {
+ selectedEntity = &instances[k];
+ }
+ }
+ }
+
+ ImGui::End();
+}
+
void RecordImGuiSceneEditor() {
if (!ImGui::Begin("SceneEditorEntityTypes", &pkeSettings.editorSettings.isShowingSceneEditor)) {
ImGui::End();
@@ -1271,6 +1301,7 @@ void RecordImGuiSceneEditor() {
if (selectedEntity != nullptr) {
static PkeArray<CompGrBinds *> entGrBinds;
static PkeArray<CompInstance *> entInstances;
+ static EntityType *entType;
bool reset = false;
if (entGrBinds.next > 0) {
if (entGrBinds.data[0]->entHandle != selectedEntity->entHandle) {
@@ -1284,6 +1315,7 @@ void RecordImGuiSceneEditor() {
if (reset) {
PkeArray_SoftReset(&entGrBinds);
PkeArray_SoftReset(&entInstances);
+ entType = nullptr;
}
if (entGrBinds.next == 0)
ECS_GetGrBinds(ECS_GetEntity(selectedEntity->entHandle), entGrBinds);
@@ -1296,6 +1328,13 @@ void RecordImGuiSceneEditor() {
entityInstancesToCreate.Push(entityType);
}
}
+ entType = EntityType_FindByEntityHandle(selectedEntity->entHandle);
+ if (entType != nullptr) {
+ ImGui::Text("%s: %s", "EntType: ", entType->entityTypeCode.val);
+ } else {
+ ImGui::Text("%s: %s", "EntType: ", "Unknown");
+ }
+ ImGui::Text("%s: %08x %08x", "Entity Handle: ", selectedEntity->entHandle.bucketIndex, selectedEntity->entHandle.itemIndex);
for (int64_t i = 0; i < entGrBinds.next; ++i) {
RecordImGui_CompGrBinds(true, entGrBinds.data[i]);
}
@@ -1315,6 +1354,7 @@ void PkeEditor_RecordImGui() {
RecordImGuiEditorWrapper();
RecordImGuiProjectSettingsEditor();
RecordImGuiProjectBrowser();
+ RecordImGuiSceneBrowser();
RecordImGuiSceneEditor();
RecordImGuiUBO();
RecordImGuiCameras();
@@ -1421,9 +1461,9 @@ void PkeEditor_Init() {
trfm.setOrigin(btVector3(-40.f, -40.f, -40.f));
trfm.setRotation(btQuaternion(0.f, 0.f, 0.f, 1.f));
- NullCamera.phys.inst->bt.motionState->setWorldTransform(trfm);
- NullCamera.phys.inst->bt.rigidBody->setWorldTransform(trfm);
- NullCamera.phys.inst->bt.rigidBody->activate();
+ NullCameraInstance.bt.motionState->setWorldTransform(trfm);
+ NullCameraInstance.bt.rigidBody->setWorldTransform(trfm);
+ NullCameraInstance.bt.rigidBody->activate();
NullCamera.type = PKE_CAMERA_TYPE_PERSPECTIVE,
NullCamera.view = PKE_CAMERA_VIEW_FREE,
NullCamera.stale = PKE_CAMERA_STALE_ALL,
diff --git a/src/camera.cpp b/src/camera.cpp
index 75aa40f..7ee9408 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -6,6 +6,7 @@
#include "ecs.hpp"
#include "math-helpers.hpp"
#include "physics.hpp"
+#include <glm/ext/quaternion_geometric.hpp>
PkeCamera NullCamera {
.camHandle = CameraHandle_MAX,
@@ -13,11 +14,12 @@ PkeCamera NullCamera {
.view = PKE_CAMERA_VIEW_TARGET,
.stale = PKE_CAMERA_STALE_ALL,
.phys = {
- .inst = nullptr,
- .targetInst = nullptr,
+ .instHandle = InstanceHandle_MAX,
+ .targetInstHandle = InstanceHandle_MAX,
.constraint = nullptr,
},
};
+CompInstance NullCameraInstance;
PkeCamera *ActiveCamera = &NullCamera;
const pk_handle_item_index_T MAX_CAMERAS_PER_BUCKET = 32;
@@ -25,43 +27,45 @@ BucketContainer<PkeCamera, CameraHandle> Camera_BucketContainer{};
btSphereShape CameraShape{1.f};
-PkeCamera &PkeCamera_Register_Inner(PkeCamera &cam, const InstPos &instPos) {
+PkeCamera &PkeCamera_Register_Inner(PkeCamera &cam, CompInstance &inst, const InstPos &instPos) {
btVector3 gravity(0.f, 0.f, 0.f);
- cam.phys.inst->physicsLayer = PhysicsCollision{0};
- cam.phys.inst->physicsMask = PhysicsCollision{0};
+ cam.phys.instHandle = inst.instanceHandle;
+ inst.physicsLayer = PhysicsCollision{0};
+ inst.physicsMask = PhysicsCollision{0};
btVector3 localInertia(0, 0, 0);
CameraShape.calculateLocalInertia(instPos.mass, localInertia);
- cam.phys.inst->bt.motionState = pk_new<btDefaultMotionState>(MemBkt_Bullet);
- new (cam.phys.inst->bt.motionState) btDefaultMotionState(instPos.posRot);
+ inst.bt.motionState = pk_new<btDefaultMotionState>(MemBkt_Bullet);
+ new (inst.bt.motionState) btDefaultMotionState(instPos.posRot);
- cam.phys.inst->bt.rigidBody = pk_new<btRigidBody>(MemBkt_Bullet);
- new (cam.phys.inst->bt.rigidBody) btRigidBody(instPos.mass, cam.phys.inst->bt.motionState, &CameraShape, localInertia);
+ inst.bt.rigidBody = pk_new<btRigidBody>(MemBkt_Bullet);
+ new (inst.bt.rigidBody) btRigidBody(instPos.mass, inst.bt.motionState, &CameraShape, localInertia);
- cam.phys.inst->bt.rigidBody->setLinearVelocity(btVector3(0,0,0));
- cam.phys.inst->bt.rigidBody->setAngularVelocity(btVector3(0,0,0));
- cam.phys.inst->bt.rigidBody->getCollisionShape()->setLocalScaling(instPos.scale);
- BtDynamicsWorld->addRigidBody(cam.phys.inst->bt.rigidBody);
- cam.phys.inst->bt.rigidBody->setGravity(gravity);
- cam.phys.inst->bt.rigidBody->getBroadphaseProxy()->m_collisionFilterGroup = static_cast<PhysicsCollision_T>(cam.phys.inst->physicsLayer);
- cam.phys.inst->bt.rigidBody->getBroadphaseProxy()->m_collisionFilterMask = static_cast<PhysicsCollision_T>(cam.phys.inst->physicsMask);
- cam.phys.inst->bt.rigidBody->setUserPointer(reinterpret_cast<void *>(cam.phys.inst));
+ inst.bt.rigidBody->setLinearVelocity(btVector3(0,0,0));
+ inst.bt.rigidBody->setAngularVelocity(btVector3(0,0,0));
+ inst.bt.rigidBody->getCollisionShape()->setLocalScaling(instPos.scale);
+ BtDynamicsWorld->addRigidBody(inst.bt.rigidBody);
+ inst.bt.rigidBody->setGravity(gravity);
+ inst.bt.rigidBody->getBroadphaseProxy()->m_collisionFilterGroup = static_cast<PhysicsCollision_T>(inst.physicsLayer);
+ inst.bt.rigidBody->getBroadphaseProxy()->m_collisionFilterMask = static_cast<PhysicsCollision_T>(inst.physicsMask);
+ inst.bt.rigidBody->setUserPointer(reinterpret_cast<void *>(&inst));
return cam;
}
PkeCamera &PkeCamera_Register(const InstPos &instPos) {
CameraHandle cameraHandle{Buckets_NewHandle(Camera_BucketContainer)};
+ CompInstance *inst;
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);
+ inst = ECS_CreateInstance(&cam, nullptr);
- return PkeCamera_Register_Inner(cam, instPos);
+ return PkeCamera_Register_Inner(cam, *inst, instPos);
}
PkeCamera *PkeCamera_Get(CameraHandle cameraHandle) {
@@ -83,38 +87,57 @@ PkeCamera *PkeCamera_Get(EntityHandle handle) {
return nullptr;
}
-void PkeCamera_AttachToInstance(CameraHandle cameraHandle, CompInstance *inst) {
+void PkeCamera_TargetInstance(CameraHandle cameraHandle, CompInstance *inst) {
assert(cameraHandle != CameraHandle_MAX);
auto &cam = Camera_BucketContainer.buckets[cameraHandle.bucketIndex][cameraHandle.itemIndex];
+ CompInstance *selfInstance = ECS_GetInstance(cam.phys.instHandle);
if (cam.phys.constraint != nullptr && cam.phys.constraint != CAFE_BABE(btTypedConstraint)) {
CompInstance *activeInst = reinterpret_cast<CompInstance *>(cam.phys.constraint->getRigidBodyB().getUserIndex());
- PkeCamera_DetachFromInstance(cameraHandle, activeInst);
+ PkeCamera_UntargetInstance(cameraHandle, activeInst);
}
btVector3 cameraOffset(0.f, -10.f, -10.f);
btTransform trfm;
+ btQuaternion bQuatRot;
inst->bt.motionState->getWorldTransform(trfm);
+
+ glm::vec3 gPos;
+ BulletToGlm(trfm.getOrigin(), gPos);
+ if (gPos != glm::vec3(0, 0, 0)) {
+ gPos = glm::normalize(-gPos);
+ }
+
+ glm::quat gQuatRot = glm::quatLookAt(-gPos, glm::vec3(0, -1, 0));
+ GlmToBullet(gQuatRot, bQuatRot);
+
trfm.setOrigin(trfm.getOrigin() + cameraOffset);
+ trfm.setRotation(bQuatRot);
- 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));
- cam.phys.inst->bt.rigidBody->setAngularVelocity(btVector3(0,0,0));
- cam.phys.inst->bt.rigidBody->activate();
+ cam.phys.targetInstHandle = inst->instanceHandle;
+ selfInstance->bt.motionState->setWorldTransform(trfm);
+ selfInstance->bt.rigidBody->setWorldTransform(trfm);
+ selfInstance->bt.rigidBody->setLinearVelocity(btVector3(0,0,0));
+ selfInstance->bt.rigidBody->setAngularVelocity(btVector3(0,0,0));
+ selfInstance->bt.rigidBody->activate();
assert(cam.phys.constraint == nullptr || cam.phys.constraint == CAFE_BABE(btTypedConstraint));
+ /* 2025-01-14 JCB
+ * This was throwing bullet3 errors, so I've decided to split the work.
+ * This commit completes the 'targeting' task, where a camera tracks a target.
+ * This may or may not make a good starting point for the 'following' task.
+ *
cam.phys.constraint = pk_new<btTypedConstraint>(MemBkt_Bullet);
- new (cam.phys.constraint) btPoint2PointConstraint(*cam.phys.inst->bt.rigidBody, *inst->bt.rigidBody, btVector3(0.f, -1.f, -1.f), cameraOffset);
+ new (cam.phys.constraint) btPoint2PointConstraint(*selfInstance->bt.rigidBody, *inst->bt.rigidBody, btVector3(0.f, -1.f, -1.f), cameraOffset);
BtDynamicsWorld->addConstraint(cam.phys.constraint);
+ */
cam.view = PKE_CAMERA_VIEW_TARGET;
cam.stale = PKE_CAMERA_STALE_POSROT;
}
-void PkeCamera_DetachFromInstance(CameraHandle cameraHandle, CompInstance *inst) {
+void PkeCamera_UntargetInstance(CameraHandle cameraHandle, CompInstance *inst) {
assert(cameraHandle != CameraHandle_MAX);
auto &cam = Camera_BucketContainer.buckets[cameraHandle.bucketIndex][cameraHandle.itemIndex];
BtDynamicsWorld->removeConstraint(cam.phys.constraint);
@@ -155,8 +178,8 @@ void PkeCamera_Destroy(CameraHandle cameraHandle) {
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.instHandle = InstanceHandle_MAX;
+ cam.phys.targetInstHandle = InstanceHandle_MAX;
cam.phys.constraint = CAFE_BABE(btTypedConstraint);
}
@@ -175,23 +198,21 @@ PkeCamera *PkeCamera_GetCameras(int64_t bucketIndex, int64_t &count) {
void PkeCamera_Init() {
Buckets_Init(Camera_BucketContainer, MAX_CAMERAS_PER_BUCKET);
- NullCamera.phys.inst = pk_new<CompInstance>();
+ memset(&NullCameraInstance, 0, sizeof(NullCameraInstance));
InstPos instPos{
.scale = btVector3(1.f, 1.f, 1.f),
.mass = 1.f,
};
- PkeCamera_Register_Inner(NullCamera, instPos);
+ PkeCamera_Register_Inner(NullCamera, NullCameraInstance, instPos);
}
void PkeCamera_Teardown() {
+ BtDynamicsWorld->removeRigidBody(NullCameraInstance.bt.rigidBody);
+ pk_delete<btDefaultMotionState>(NullCameraInstance.bt.motionState, MemBkt_Bullet);
+ pk_delete<btRigidBody>(NullCameraInstance.bt.rigidBody, MemBkt_Bullet);
+ NullCameraInstance.bt.motionState = CAFE_BABE(btDefaultMotionState);
+ NullCameraInstance.bt.rigidBody = CAFE_BABE(btRigidBody);
Buckets_Destroy(Camera_BucketContainer);
- BtDynamicsWorld->removeRigidBody(NullCamera.phys.inst->bt.rigidBody);
- pk_delete<btDefaultMotionState>(NullCamera.phys.inst->bt.motionState, MemBkt_Bullet);
- pk_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);
- pk_delete<CompInstance>(NullCamera.phys.inst);
- NullCamera.phys.inst = CAFE_BABE(CompInstance);
}
void PkeCamera_Tick(double delta) {
@@ -210,16 +231,17 @@ void PkeCamera_Tick(double delta) {
long itemCount = Camera_BucketContainer.pkeHandle.bucketIndex == b ? Camera_BucketContainer.pkeHandle.itemIndex : Camera_BucketContainer.limits.itemIndex;
for (pk_handle_item_index_T i = 0; i < itemCount; ++i) {
auto &cam = bkt[i];
- if (cam.handle == EntityHandle_MAX) {
+ if (cam.handle == EntityHandle_MAX || cam.phys.instHandle == InstanceHandle_MAX) {
continue;
}
- 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) {
+ CompInstance *inst = ECS_GetInstance(cam.phys.instHandle);
+ assert(inst != nullptr);
+ if (inst->isNeedingUpdated == true) {
cam.stale = cam.stale | PKE_CAMERA_STALE_POSROT;
+ inst->isNeedingUpdated = false;
}
+ if (cam.phys.targetInstHandle == InstanceHandle_MAX) continue;
+ cam.stale = cam.stale | PKE_CAMERA_STALE_POSROT;
}
}
}
diff --git a/src/camera.hpp b/src/camera.hpp
index f4cc986..82712fe 100644
--- a/src/camera.hpp
+++ b/src/camera.hpp
@@ -33,21 +33,22 @@ struct PkeCamera : public Entity_Base {
PkeCameraView view = PkeCameraView_MAX;
PkeCameraStaleFlags stale = PkeCameraStaleFlags_MAX;
struct Phys {
- CompInstance *inst = nullptr;
- CompInstance *targetInst = nullptr;
+ InstanceHandle instHandle;
+ InstanceHandle targetInstHandle;
btTypedConstraint *constraint = nullptr;
} phys;
bool isPrimary = false;
};
extern PkeCamera NullCamera;
+extern CompInstance NullCameraInstance;
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);
+void PkeCamera_TargetInstance(CameraHandle cameraHandle, CompInstance *inst);
+void PkeCamera_UntargetInstance(CameraHandle cameraHandle, CompInstance *inst);
int64_t PkeCamera_GetBucketCount();
PkeCamera *PkeCamera_GetCameras(int64_t bucketIndex, int64_t &count);
void PkeCamera_SetPrimary(CameraHandle handle);
diff --git a/src/entities.cpp b/src/entities.cpp
index e955578..0fa5cf2 100644
--- a/src/entities.cpp
+++ b/src/entities.cpp
@@ -102,7 +102,7 @@ EntityType *EntityType_FindByTypeCode(const char *typeCode) {
return nullptr;
}
-EntityType *EntityType_FindByEntityHandle(EntityHandle handle) {
+EntityType *EntityType_FindByEntityHandle_Inner(EntityHandle handle) {
if (handle == EntityHandle_MAX) return nullptr;
for (pk_handle_bucket_index_T b = 0; b <= EntityType_BC.pkeHandle.bucketIndex; ++b) {
auto &bkt = EntityType_BC.buckets[b];
@@ -116,6 +116,20 @@ EntityType *EntityType_FindByEntityHandle(EntityHandle handle) {
}
return nullptr;
}
+EntityType *EntityType_FindByEntityHandle(EntityHandle handle) {
+ Entity_Base *base_entity;
+ EntityType *ret = nullptr;
+ EntityHandle h = handle;
+ while (ret == nullptr) {
+ ret = EntityType_FindByEntityHandle_Inner(h);
+ if (ret != nullptr) return ret;
+ base_entity = ECS_GetEntity(h);
+ if (base_entity == nullptr) break;
+ h = base_entity->parentHandle;
+ if (h == EntityHandle_MAX) break;
+ }
+ return nullptr;
+}
void CalculateCombinedMemReqs(uint64_t memReqsCount, VkMemoryRequirements *memReqs, VkMemoryRequirements &combinedMemReqs) {
combinedMemReqs.size = 0;
diff --git a/src/game.cpp b/src/game.cpp
index 220aebd..be4bb25 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -36,8 +36,8 @@ const long readLineLength = 128;
char readLine[readLineLength];
struct InstMapping {
InstanceHandle origHandle = InstanceHandle_MAX;
- Entity_Base *newEnt = nullptr;
- CompInstance *newInst = nullptr;
+ EntityHandle newEntHandle;
+ InstanceHandle newInstHandle;
InstPos newInstance{};
};
PkeArray<InstMapping> loadFileInstanceMappings{};
@@ -82,12 +82,12 @@ void SerializeCamera(std::ostringstream &stream, const PkeCamera &cam) {
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, 22, "0x%08X 0x%08X", cam.phys.inst->instanceHandle.bucketIndex, cam.phys.inst->instanceHandle.itemIndex);
+ if (cam.phys.instHandle != InstanceHandle_MAX) {
+ snprintf(handleStr, 22, "0x%08X 0x%08X", cam.phys.instHandle.bucketIndex, cam.phys.instHandle.itemIndex);
stream << PKE_FILE_CAMERA_INSTANCE_HANDLE << handleStr << std::endl;
}
- if (cam.phys.targetInst != c.phys.targetInst && cam.phys.targetInst != CAFE_BABE(CompInstance)) {
- snprintf(handleStr, 22, "0x%08X 0x%08X", cam.phys.targetInst->instanceHandle.bucketIndex, cam.phys.targetInst->instanceHandle.itemIndex);
+ if (cam.phys.targetInstHandle != InstanceHandle_MAX) {
+ snprintf(handleStr, 22, "0x%08X 0x%08X", cam.phys.targetInstHandle.bucketIndex, cam.phys.targetInstHandle.itemIndex);
stream << PKE_FILE_CAMERA_TARGET_INSTANCE_HANDLE << handleStr << std::endl;
}
if (cam.isPrimary != c.isPrimary) {
@@ -107,11 +107,11 @@ void SerializeInstance(std::ostringstream &stream, const CompInstance &comp) {
baseInst.posRot.setIdentity();
baseInst.scale = btVector3(1, 1, 1);
baseInst.mass = 1;
- if (comp.entHandle != c.entHandle) {
+ if (comp.entHandle != InstanceHandle_MAX) {
snprintf(handleStr, 22, "0x%08X 0x%08X", comp.entHandle.bucketIndex, comp.entHandle.itemIndex);
stream << PKE_FILE_INSTANCE_ENTITY_HANDLE << handleStr << std::endl;
}
- if (comp.entHandle != c.entHandle) {
+ if (comp.instanceHandle != InstanceHandle_MAX) {
snprintf(handleStr, 22, "0x%08X 0x%08X", comp.instanceHandle.bucketIndex, comp.instanceHandle.itemIndex);
stream << PKE_FILE_INSTANCE_HANDLE << handleStr << std::endl;
}
@@ -190,9 +190,10 @@ void ParseCamera(PkeLevel *level, std::ifstream &stream) {
rCam.type = cam.type;
rCam.view = cam.view;
rCam.isPrimary = cam.isPrimary;
+ rCam.phys.targetInstHandle = targetInstanceHandle;
PkeLevel_RegisterCamera(level->levelHandle, rCam.camHandle);
if (targetInstanceIndex > -1) {
- PkeCamera_AttachToInstance(rCam.camHandle, loadFileInstanceMappings.data[targetInstanceIndex].newInst);
+ PkeCamera_TargetInstance(rCam.camHandle, ECS_GetInstance(loadFileInstanceMappings.data[targetInstanceIndex].newInstHandle));
}
if (rCam.isPrimary == true) {
ActiveCamera = &rCam;
@@ -250,6 +251,8 @@ void ParseInstance(Entity_Base *parentEntity, std::ifstream &stream) {
CompInstance comp{};
InstMapping mapping {
.origHandle = InstanceHandle_MAX,
+ .newEntHandle = EntityHandle_MAX,
+ .newInstHandle = InstanceHandle_MAX,
.newInstance = {
.scale = btVector3(1.f, 1.f, 1.f),
.mass = 1.f,
@@ -261,6 +264,7 @@ void ParseInstance(Entity_Base *parentEntity, std::ifstream &stream) {
while (stream.getline(readLine, readLineLength)) {
if (strstr(PKE_FILE_OBJ_END, readLine)) {
EntityType *etPtr = nullptr;
+ Entity_Base *entity = nullptr;
bool skipEntCreate = false;
if (strlen(entTypeCode) > 1) {
etPtr = EntityType_FindByTypeCode(entTypeCode);
@@ -281,18 +285,19 @@ void ParseInstance(Entity_Base *parentEntity, std::ifstream &stream) {
if (skipEntCreate == false) {
if (etPtr != nullptr && etPtr->createInstanceCallback.func != nullptr) {
typedef Entity_Base *CreateInst();
- mapping.newEnt = reinterpret_cast<CreateInst*>(etPtr->createInstanceCallback.func)();
+ entity = reinterpret_cast<CreateInst*>(etPtr->createInstanceCallback.func)();
} else {
- mapping.newEnt = EntityType_CreateGenericInstance(etPtr, parentEntity, &comp, &mapping.newInstance);
+ entity = EntityType_CreateGenericInstance(etPtr, parentEntity, &comp, &mapping.newInstance);
fprintf(stdout ,"[Game::ParseInstance] Debug: entTypeCode '%s' does not have a registered callback func to handle instance creation.\n", entTypeCode);
}
+ mapping.newEntHandle = entity->handle;
}
- if (mapping.newEnt != nullptr) {
+ if (mapping.newEntHandle != EntityHandle_MAX) {
// TODO this is messy
PkeArray<CompInstance *> instances{};
- ECS_GetInstances(mapping.newEnt, instances);
+ ECS_GetInstances(entity, instances);
assert(instances.next > 0);
- mapping.newInst = instances.data[0];
+ mapping.newInstHandle = instances.data[0]->instanceHandle;
}
PkeArray_Add(&loadFileInstanceMappings, mapping);
break;
diff --git a/src/window.cpp b/src/window.cpp
index f5821ae..e44b498 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -909,10 +909,17 @@ void UpdatePresentDescriptorSets() {
void UpdateCamera() {
if (ActiveCamera->stale == PkeCameraStaleFlags{0}) return;
+ CompInstance *inst = nullptr;
+ CompInstance *targetInst = nullptr;
glm::vec3 gPos;
glm::quat gRot;
btTransform trfm;
- ActiveCamera->phys.inst->bt.motionState->getWorldTransform(trfm);
+ if (ActiveCamera == &NullCamera) {
+ inst = &NullCameraInstance;
+ } else {
+ inst = ECS_GetInstance(ActiveCamera->phys.instHandle);
+ }
+ inst->bt.motionState->getWorldTransform(trfm);
BulletToGlm(trfm.getOrigin(), gPos);
BulletToGlm(trfm.getRotation(), gRot);
if (bool(ActiveCamera->stale & PKE_CAMERA_STALE_POS)) {
@@ -923,12 +930,13 @@ void UpdateCamera() {
UBO.view = glm::mat4_cast(gRot);
} else if (bool(ActiveCamera->view == PKE_CAMERA_VIEW_TARGET)) {
glm::vec3 gTargetPos{0.f, 0.f, 0.f};
- if (ActiveCamera->phys.targetInst != nullptr && ActiveCamera->phys.targetInst != CAFE_BABE(CompInstance)) {
+ targetInst = ECS_GetInstance(ActiveCamera->phys.targetInstHandle);
+ if (targetInst != nullptr && targetInst != CAFE_BABE(CompInstance)) {
btTransform targetTrfm;
- ActiveCamera->phys.targetInst->bt.motionState->getWorldTransform(targetTrfm);
- BulletToGlm(trfm.getOrigin(), gTargetPos);
+ targetInst->bt.motionState->getWorldTransform(targetTrfm);
+ BulletToGlm(targetTrfm.getOrigin(), gTargetPos);
}
- UBO.view = glm::lookAt(glm::vec3(0), gPos - gTargetPos, glm::vec3(0.f, 1.f, 0.f));
+ 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)) {