summaryrefslogtreecommitdiff
path: root/src/camera.cpp
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 /src/camera.cpp
parent46d814de510d0a7753c3e49eed3b3440d1c7c681 (diff)
pke: camera can track a given target
Diffstat (limited to 'src/camera.cpp')
-rw-r--r--src/camera.cpp114
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;
}
}
}