194 return id == other.id;
201 std::vector<SpatialIndex> results;
202 ::t2d::TileBodyCollisionCache<TileData> detectionCache;
204 std::vector<std::pair<uint16_t, AABB<Float>>> shouldMove;
205 std::vector<std::pair<uint32_t, uint32_t>> couldCollide;
209 uint16_t element = std::numeric_limits<uint16_t>::max();
224 : m_bodyList(m_bodies), m_grid(tileWidth * 20), ioServiceWork(ioService) {
225 threadCount = std::min(threadCount, (
size_t)boost::thread::hardware_concurrency());
227 std::pair<boost::thread::id, Cache> pair;
228 pair.first = boost::this_thread::get_id();
229 m_threadCache.insert(pair);
231 for (
size_t i = 0; i < threadCount; i++) {
232 boost::thread* thread = threadPool.create_thread(boost::bind(&boost::asio::io_service::run, &ioService));
234 std::pair<boost::thread::id, Cache> pair;
235 pair.first = thread->get_id();
236 m_threadCache.insert(pair);
242 threadPool.join_all();
249 uint32_t newId = m_bodies.insert();
252 bodyElement.body = m_tileBodyPool.template construct<TileMapT&, uint32_t>(tileMap, newId);
253 if (!bodyElement.body)
256 m_bodyList.push_back(bodyElement.body->m_id);
258 insertIntoTree(bodyElement.body);
260 return bodyElement.body;
274 uint32_t newId = m_bodies.insert();
277 bodyElement.body = m_bulletBodyPool.template construct<uint32_t, Float>(newId, radius);
278 if (!bodyElement.body)
281 m_bodyList.push_back(bodyElement.body->m_id);
283 bodyElement.body->addLinearVelocity(initialLinearVelocity);
285 insertIntoTree(bodyElement.body);
287 return bodyElement.body;
296 switch (body->m_bodyType) {
301 case BodyType::Bullet:
302 m_bulletBodyPool.destroy(
dynamic_cast<BulletBody*
>(body));
310 m_bodyList.remove_element(body->m_id);
311 m_bodies.erase(body->m_id);
320 void update(
const Float dt,
size_t steps) {
321 auto start = std::chrono::steady_clock::now();
323 Float timePerStep = dt / (Float)steps;
325 for (
size_t i = 0; i < steps; i++) {
327 executeOnBodies(timePerStep, &World::updateBodies);
332 executeOnBodies(timePerStep, &World::batchQuery);
334 std::vector<CollisionManifold> manifolds;
335 Cache& mainThreadCache = m_threadCache[boost::this_thread::get_id()];
336 for (
const std::pair<uint32_t, uint32_t>& collidingPair : m_possibleCollisions) {
337 WorldBody* body = m_bodies[collidingPair.first].body;
338 WorldBody* otherBody = m_bodies[collidingPair.second].body;
340 vec2 body1Offset(0.0);
341 vec2 body2Offset(0.0);
345 switch (body->m_bodyType) {
346 case BodyType::Tile: {
347 switch (otherBody->m_bodyType) {
349 detectTileBodyCollision<TileData>(
dynamic_cast<TileBodyT&
>(*body),
dynamic_cast<TileBodyT&
>(*otherBody), mainThreadCache.detectionCache, manifolds, body1Offset, body2Offset);
366 body->
moveBy(body1Offset);
367 otherBody->
moveBy(body2Offset);
369 m_possibleCollisions.clear();
373 auto end = std::chrono::steady_clock::now();
375 m_executionTimeAvgTotal += std::chrono::duration_cast<std::chrono::duration<Float, std::milli>>(end - start).count();
376 m_executionTimeAvgCount++;
385 Float avg = m_executionTimeAvgTotal / m_executionTimeAvgCount;
387 m_executionTimeAvgTotal = 0;
388 m_executionTimeAvgCount = 0;
398 return m_worldForces.gravity;
407 m_worldForces.gravity = gravity;
421 void executeOnBodies(Float timePerStep, Func&& func) {
423 size_t threadPoolSize = threadPool.size() + 1;
424 size_t bodiesPerThread = m_bodyList.size() / threadPoolSize;
425 for (
size_t i = 0; i < threadPoolSize; i++) {
426 size_t bodyStart = i * bodiesPerThread;
427 size_t bodyEnd = bodyStart + bodiesPerThread;
430 if (i + 1 == threadPoolSize) {
431 bodyEnd = m_bodyList.size();
432 (this->*func)(timePerStep, bodyStart, bodyEnd);
434 ioService.post(boost::bind(func,
this, timePerStep, bodyStart, bodyEnd));
437 while (jobsDone < threadPoolSize) {}
440 void updateBodies(Float timePerStep,
size_t start,
size_t end) {
441 Cache& cache = m_threadCache.find(boost::this_thread::get_id())->second;
442 cache.shouldMove.clear();
444 typename BodyList::Iterator i = m_bodyList.begin();
445 for (
size_t index = 0; index < end; index++, ++i) {
451 body->
addLinearVel(m_worldForces.gravity * timePerStep);
454 if (body->m_flags[Body::NEEDS_REINSERT]) {
455 cache.shouldMove.emplace_back(std::pair<uint16_t,
AABB<Float>>(i->element, body->
getAABB()));
456 body->m_flags[Body::NEEDS_REINSERT] =
false;
461 for (
auto& movePair : cache.shouldMove) {
462 m_grid.relocate(movePair.first, movePair.second);
469 void batchQuery(Float timePerStep,
size_t start,
size_t end) {
470 Cache& cache = m_threadCache.find(boost::this_thread::get_id())->second;
471 cache.couldCollide.clear();
473 typename BodyList::Iterator i = m_bodyList.begin();
474 for (
size_t index = 0; index < end; index++, ++i) {
480 m_grid.queryIntersects(bodyAABB, [&](
const SpatialIndex& spatialIndex) {
481 if (spatialIndex.id == body->
id())
483 if (body->
isStatic() && m_bodies[spatialIndex.id].body->isStatic())
486 cache.couldCollide.push_back(std::pair(body->
id(), spatialIndex.id));
490 m_collisionListLock.lock();
491 m_possibleCollisions.insert(m_possibleCollisions.end(), cache.couldCollide.begin(), cache.couldCollide.end());
492 m_collisionListLock.unlock();
498 BodyElement& bodyElement = m_bodies[body->
id()];
499 bodyElement.element = m_grid.insert(body->
getAABB(), SpatialIndex{ body->id() });
503 BodyElement& bodyElement = m_bodies[body->
id()];
504 m_grid.erase(bodyElement->element);
508 FlatMap<boost::thread::id, Cache> m_threadCache;
512 boost::object_pool<TileBodyT> m_tileBodyPool;
513 boost::object_pool<BulletBody> m_bulletBodyPool;
515 boost::mutex m_gridLock;
517 boost::mutex m_collisionListLock;
518 std::vector<std::pair<uint32_t, uint32_t>> m_possibleCollisions;
520 Float m_executionTimeAvgCount = 0;
521 Float m_executionTimeAvgTotal = 0;
523 boost::asio::io_service ioService;
524 boost::asio::io_service::work ioServiceWork;
525 boost::thread_group threadPool;
526 std::atomic<size_t> jobsDone;
529 vec2 gravity = { 0.0f, 0.0f };
Extends the functionality of WorldBody to allow for things such as angular velocity.
Definition body.hpp:238
For use with a TileMap<>, allows collisions with other rigid bodies inside World<>
Definition tileMap.hpp:271
The abstract base class of all Rigid Bodies that defines essential methods and members to be used in ...
Definition body.hpp:30
void addLinearVel(const vec2 &vel)
applies a linear velocity to this body
Definition body.hpp:180
virtual AABB< Float > getAABB() const =0
Returns the AABB of this body.
bool isStatic() const
Returns if the body is static, meaning it cannot be moved by forces or other bodies.
Definition body.hpp:135
virtual void integrate(Float dt)=0
Integerates this body, meaning the linear velocity and angular velocity will be integrated into the p...
void moveBy(const vec2 &amount)
Moves the body by amount.
Definition body.hpp:81
uint32_t id() const
Returns the id assigned to this body the physics world.
Definition body.hpp:48