summaryrefslogtreecommitdiff
path: root/src/physics.cpp
blob: e9600598bab29974c077d54874e804e7d5b01e75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

#include "physics.hpp"

#include "components.hpp"
#include "dynamic-array.hpp"
#include "game-settings.hpp"

#include <LinearMath/btAlignedAllocator.h>
#include <btBulletDynamicsCommon.h>
#include <BulletCollision/BroadphaseCollision/btOverlappingPairCache.h>
#include <BulletDynamics/Dynamics/btRigidBody.h>

TypeSafeInt_B(PhysicsCollision);

MemBucket *MemBkt_Bullet = nullptr;
btDiscreteDynamicsWorld *BtDynamicsWorld = nullptr;

struct AllocedData {
	void *data;
	std::size_t size;
};
DynArray<AllocedData> *bulletAllocs;

btDefaultCollisionConfiguration *btConfiguration = nullptr;
btCollisionDispatcher *btDispatcher = nullptr;
btBroadphaseInterface *btBroadphase = nullptr;
btConstraintSolver *btSolver = nullptr;

void *pke_btAlignedAllocFunc(size_t size, int alignment) {
	void *ptr = Pke_New(size, alignment, MemBkt_Bullet);
	bulletAllocs->Push({ptr, size});
	return ptr;
}
void pke_btAlignedFreeFunc(void *memBlock) {
	auto &arr = *bulletAllocs;
	auto count = arr.Count();
	long index = -1;
	for (long i = 0; i < count; ++i) {
		if (arr[i].data == memBlock) {
			index = i;
			break;
		}
	}
	assert(index != -1);
	Pke_Delete(const_cast<void *>(memBlock), arr[index].size, MemBkt_Bullet);
	bulletAllocs->Remove(index);
}
void *pke_btAllocFunc(size_t size) {
	void *ptr = Pke_New(size, MINIMUM_ALIGNMENT, MemBkt_Bullet);
	bulletAllocs->Push({ptr, size});
	return ptr;
}
void pke_btFreeFunc(void *memBlock) {
	auto &arr = *bulletAllocs;
	auto count = arr.Count();
	long index = -1;
	for (long i = 0; i < count; ++i) {
		if (arr[i].data == memBlock) {
			index = i;
			break;
		}
	}
	assert(index != -1);
	Pke_Delete(const_cast<void *>(memBlock), arr[index].size, MemBkt_Bullet);
	bulletAllocs->Remove(index);
}

struct CollisionHandlerStruct : public btOverlapFilterCallback {
	~CollisionHandlerStruct() override {}
	bool needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const override {
		return (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) ||
			(proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
	}
} collisionHandlerStruct;

void Physics_Init() {
	MemBkt_Bullet = Pke_BeginTransientBucket();
	bulletAllocs = Pke_New<DynArray<AllocedData>>(MemBkt_Bullet);
	new (bulletAllocs) DynArray<AllocedData>(MemBkt_Bullet);
	bulletAllocs->Reserve(1024);
	btAlignedAllocSetCustom(pke_btAllocFunc, pke_btFreeFunc);
	btAlignedAllocSetCustomAligned(pke_btAlignedAllocFunc, pke_btAlignedFreeFunc);

	btConfiguration = Pke_New<btDefaultCollisionConfiguration>(MemBkt_Bullet);
	btDispatcher = Pke_New<btCollisionDispatcher>(MemBkt_Bullet);
	new (btDispatcher) btCollisionDispatcher(btConfiguration);

	btBroadphase = Pke_New<btDbvtBroadphase>(MemBkt_Bullet);
#if 1
	btHashedOverlappingPairCache *overlappingPairCache = Pke_New<btHashedOverlappingPairCache>(MemBkt_Bullet);
	overlappingPairCache->setOverlapFilterCallback(&collisionHandlerStruct);
	new (btBroadphase) btDbvtBroadphase(overlappingPairCache);
#else
	new (btBroadphase) btDbvtBroadphase();
#endif
	btSolver = Pke_New<btSequentialImpulseConstraintSolver>(MemBkt_Bullet);

	BtDynamicsWorld = Pke_New<btDiscreteDynamicsWorld>(MemBkt_Bullet);
	new (BtDynamicsWorld) btDiscreteDynamicsWorld(btDispatcher, btBroadphase, btSolver, btConfiguration);
}

int32_t Physics_Tick(double delta) {
	if (pkeSettings.isSimulationPaused == true)
		return 0;
	return BtDynamicsWorld->stepSimulation(delta, 1);
}

void Physics_Teardown() {
	Pke_EndTransientBucket(MemBkt_Bullet);
}