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 /src/camera.cpp | |
| parent | 46d814de510d0a7753c3e49eed3b3440d1c7c681 (diff) | |
pke: camera can track a given target
Diffstat (limited to 'src/camera.cpp')
| -rw-r--r-- | src/camera.cpp | 114 |
1 files changed, 68 insertions, 46 deletions
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; } } } |
