diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-01-14 15:50:04 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-01-14 15:50:04 -0500 |
| commit | 80a67230fe192287503092a3d256aea3a494409c (patch) | |
| tree | 187f2e7a41e0cd206d9969284a3abce4028d89f5 | |
| parent | 46d814de510d0a7753c3e49eed3b3440d1c7c681 (diff) | |
pke: camera can track a given target
| -rw-r--r-- | editor/editor.cpp | 96 | ||||
| -rw-r--r-- | src/camera.cpp | 114 | ||||
| -rw-r--r-- | src/camera.hpp | 9 | ||||
| -rw-r--r-- | src/entities.cpp | 16 | ||||
| -rw-r--r-- | src/game.cpp | 33 | ||||
| -rw-r--r-- | src/window.cpp | 18 |
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)) { |
