523 lines
23 KiB
C++
523 lines
23 KiB
C++
/********************************************************************************
|
|
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
|
|
* Copyright (c) 2010-2018 Daniel Chappuis *
|
|
*********************************************************************************
|
|
* *
|
|
* This software is provided 'as-is', without any express or implied warranty. *
|
|
* In no event will the authors be held liable for any damages arising from the *
|
|
* use of this software. *
|
|
* *
|
|
* Permission is granted to anyone to use this software for any purpose, *
|
|
* including commercial applications, and to alter it and redistribute it *
|
|
* freely, subject to the following restrictions: *
|
|
* *
|
|
* 1. The origin of this software must not be misrepresented; you must not claim *
|
|
* that you wrote the original software. If you use this software in a *
|
|
* product, an acknowledgment in the product documentation would be *
|
|
* appreciated but is not required. *
|
|
* *
|
|
* 2. Altered source versions must be plainly marked as such, and must not be *
|
|
* misrepresented as being the original software. *
|
|
* *
|
|
* 3. This notice may not be removed or altered from any source distribution. *
|
|
* *
|
|
********************************************************************************/
|
|
|
|
// Libraries
|
|
#include "ProxyShapesComponents.h"
|
|
#include "engine/EntityManager.h"
|
|
#include "collision/ProxyShape.h"
|
|
#include <cassert>
|
|
#include <random>
|
|
|
|
// We want to use the ReactPhysics3D namespace
|
|
using namespace reactphysics3d;
|
|
|
|
// Constructor
|
|
ProxyShapesComponents::ProxyShapesComponents(MemoryAllocator& allocator)
|
|
:mMemoryAllocator(allocator), mNbComponents(0), mNbAllocatedComponents(0),
|
|
mSleepingStartIndex(0), mBuffer(nullptr), mMapEntityToComponentIndex(allocator),
|
|
mMapProxyShapeToComponentIndex(allocator) {
|
|
|
|
// Allocate memory for the components data
|
|
allocate(INIT_ALLOCATED_COMPONENTS);
|
|
}
|
|
|
|
// Destructor
|
|
ProxyShapesComponents::~ProxyShapesComponents() {
|
|
|
|
if (mNbAllocatedComponents > 0) {
|
|
|
|
// Destroy all the remaining components
|
|
for (uint32 i = 0; i < mNbComponents; i++) {
|
|
|
|
// TODO : MAke sure we do not delete already deleted components
|
|
destroyComponent(i);
|
|
}
|
|
|
|
// Size for the data of a single component (in bytes)
|
|
const size_t totalSizeBytes = mNbAllocatedComponents * COMPONENT_DATA_SIZE;
|
|
|
|
// Release the allocated memory
|
|
mMemoryAllocator.release(mBuffer, totalSizeBytes);
|
|
}
|
|
}
|
|
|
|
// Allocate memory for a given number of components
|
|
void ProxyShapesComponents::allocate(uint32 nbComponentsToAllocate) {
|
|
|
|
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
|
|
|
// Size for the data of a single component (in bytes)
|
|
const size_t totalSizeBytes = nbComponentsToAllocate * COMPONENT_DATA_SIZE;
|
|
|
|
// Allocate memory
|
|
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
|
assert(newBuffer != nullptr);
|
|
|
|
// New pointers to components data
|
|
Entity* newEntities = static_cast<Entity*>(newBuffer);
|
|
ProxyShape** newProxyShapes = reinterpret_cast<ProxyShape**>(newEntities + nbComponentsToAllocate);
|
|
int* newBroadPhaseIds = reinterpret_cast<int*>(newProxyShapes + nbComponentsToAllocate);
|
|
AABB* newLocalBounds = reinterpret_cast<AABB*>(newBroadPhaseIds + nbComponentsToAllocate);
|
|
Transform* newLocalToBodyTransforms = reinterpret_cast<Transform*>(newLocalBounds + nbComponentsToAllocate);
|
|
CollisionShape** newCollisionShapes = reinterpret_cast<CollisionShape**>(newLocalToBodyTransforms + nbComponentsToAllocate);
|
|
decimal* newMasses = reinterpret_cast<decimal*>(newCollisionShapes + nbComponentsToAllocate);
|
|
uint32* newPreviousBodyProxyShapes = reinterpret_cast<uint32*>(newMasses + nbComponentsToAllocate);
|
|
uint32* newNextBodyProxyShapes = reinterpret_cast<uint32*>(newPreviousBodyProxyShapes + nbComponentsToAllocate);
|
|
unsigned short* newCollisionCategoryBits = reinterpret_cast<unsigned short*>(newNextBodyProxyShapes + nbComponentsToAllocate);
|
|
unsigned short* newCollideWithMaskBits = reinterpret_cast<unsigned short*>(newCollisionCategoryBits + nbComponentsToAllocate);
|
|
|
|
// If there was already components before
|
|
if (mNbComponents > 0) {
|
|
|
|
// Copy component data from the previous buffer to the new one
|
|
memcpy(newEntities, mEntities, mNbComponents * sizeof(Entity));
|
|
memcpy(newProxyShapes, mProxyShapes, mNbComponents * sizeof(ProxyShape*));
|
|
memcpy(newBroadPhaseIds, mBroadPhaseIds, mNbComponents * sizeof(int));
|
|
memcpy(newLocalBounds, mLocalBounds, mNbComponents * sizeof(AABB));
|
|
memcpy(newLocalToBodyTransforms, mLocalToBodyTransforms, mNbComponents * sizeof(Transform));
|
|
memcpy(newCollisionShapes, mCollisionShapes, mNbComponents * sizeof(CollisionShape*));
|
|
memcpy(newMasses, mMasses, mNbComponents * sizeof(decimal));
|
|
memcpy(newPreviousBodyProxyShapes, mPreviousBodyProxyShapes, mNbComponents * sizeof(uint32));
|
|
memcpy(newNextBodyProxyShapes, mNextBodyProxyShapes, mNbComponents * sizeof(uint32));
|
|
memcpy(newCollisionCategoryBits, mCollisionCategoryBits, mNbComponents * sizeof(unsigned short));
|
|
memcpy(newCollideWithMaskBits, mCollideWithMaskBits, mNbComponents * sizeof(unsigned short));
|
|
|
|
// Deallocate previous memory
|
|
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * COMPONENT_DATA_SIZE);
|
|
}
|
|
|
|
mBuffer = newBuffer;
|
|
mEntities = newEntities;
|
|
mProxyShapes = newProxyShapes;
|
|
mBroadPhaseIds = newBroadPhaseIds;
|
|
mLocalBounds = newLocalBounds;
|
|
mLocalToBodyTransforms = newLocalToBodyTransforms;
|
|
mCollisionShapes = newCollisionShapes;
|
|
mMasses = newMasses;
|
|
mPreviousBodyProxyShapes = newPreviousBodyProxyShapes;
|
|
mNextBodyProxyShapes = newNextBodyProxyShapes;
|
|
mCollisionCategoryBits = newCollisionCategoryBits;
|
|
mCollideWithMaskBits = newCollideWithMaskBits;
|
|
|
|
mNbAllocatedComponents = nbComponentsToAllocate;
|
|
}
|
|
|
|
// Add a new proxy-shape at the beginning of the linked-list of proxy-shapes of a given entity
|
|
// If it is the first proxy-shape for the entity, it will create the first item of the linked-list
|
|
void ProxyShapesComponents::linkProxyShapeWithEntity(Entity entity, uint32 proxyShapeComponentIndex) {
|
|
|
|
auto it = mMapEntityToComponentIndex.find(entity);
|
|
if (it != mMapEntityToComponentIndex.end()) {
|
|
|
|
// Get the first proxy-shape of the linked-list
|
|
uint32 firstProxyShapeIndex = (*it).second;
|
|
|
|
assert(!hasPreviousProxyShape(firstProxyShapeIndex));
|
|
|
|
// Update the previous index of the first item of the list
|
|
mPreviousBodyProxyShapes[firstProxyShapeIndex] = proxyShapeComponentIndex;
|
|
|
|
// Map the entity to the new head of the linked-list
|
|
mMapEntityToComponentIndex[entity] = proxyShapeComponentIndex;
|
|
|
|
// Add the new proxy-shape at the beginning of the linked-list
|
|
const uint32 nextIndex = firstProxyShapeIndex;
|
|
const uint32 previousIndex = proxyShapeComponentIndex;
|
|
new (mNextBodyProxyShapes + proxyShapeComponentIndex) uint32(nextIndex);
|
|
new (mPreviousBodyProxyShapes + proxyShapeComponentIndex) uint32(previousIndex);
|
|
|
|
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[proxyShapeComponentIndex]] == proxyShapeComponentIndex);
|
|
}
|
|
else { // If the entity does not have a proxy-shape yet
|
|
|
|
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, proxyShapeComponentIndex));
|
|
|
|
// The new proxy-shape has no previous/next components in the linked-list
|
|
new (mNextBodyProxyShapes + proxyShapeComponentIndex) uint32(proxyShapeComponentIndex);
|
|
new (mPreviousBodyProxyShapes + proxyShapeComponentIndex) uint32(proxyShapeComponentIndex);
|
|
|
|
assert(!hasNextProxyShape(proxyShapeComponentIndex));
|
|
}
|
|
|
|
assert(!hasPreviousProxyShape(proxyShapeComponentIndex));
|
|
}
|
|
|
|
// Add a component
|
|
void ProxyShapesComponents::addComponent(Entity entity, bool isSleeping, const ProxyShapeComponent& component) {
|
|
|
|
// If we need to allocate more components
|
|
if (mNbComponents == mNbAllocatedComponents) {
|
|
allocate(mNbAllocatedComponents * 2);
|
|
}
|
|
|
|
uint32 index;
|
|
|
|
// If the component to add is part of a sleeping entity
|
|
if (isSleeping) {
|
|
|
|
// Add the component at the end of the array
|
|
index = mNbComponents;
|
|
|
|
mSleepingStartIndex = index;
|
|
}
|
|
// If the component to add is not part of a sleeping entity
|
|
else {
|
|
|
|
// If there already are sleeping components
|
|
if (mSleepingStartIndex != mNbComponents) {
|
|
|
|
// Move the first sleeping component to the end of the array
|
|
moveComponentToIndex(mSleepingStartIndex, mNbComponents);
|
|
}
|
|
|
|
index = mSleepingStartIndex;
|
|
|
|
mSleepingStartIndex++;
|
|
}
|
|
|
|
// Insert the new component data
|
|
new (mEntities + index) Entity(entity);
|
|
mProxyShapes[index] = (component.proxyShape);
|
|
new (mBroadPhaseIds + index) int(component.broadPhaseId);
|
|
new (mLocalBounds + index) AABB(component.localBounds);
|
|
new (mLocalToBodyTransforms + index) Transform(component.localToBodyTransform);
|
|
mCollisionShapes[index] = component.collisionShape;
|
|
new (mMasses + index) decimal(component.mass);
|
|
new (mCollisionCategoryBits + index) unsigned short(component.collisionCategoryBits);
|
|
new (mCollideWithMaskBits + index) unsigned short(component.collideWithMaskBits);
|
|
|
|
mMapProxyShapeToComponentIndex.add(Pair<const ProxyShape*, uint32>(component.proxyShape, index));
|
|
|
|
mNbComponents++;
|
|
|
|
// Map the entity with the new component lookup index
|
|
linkProxyShapeWithEntity(entity, index);
|
|
|
|
assert(mSleepingStartIndex <= mNbComponents);
|
|
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index || !hasNextProxyShape(index));
|
|
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] == index || !hasPreviousProxyShape(index));
|
|
}
|
|
|
|
// Move a component from a source to a destination index in the components array
|
|
// The destination location must contain a constructed object
|
|
void ProxyShapesComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) {
|
|
|
|
const Entity entity = mEntities[srcIndex];
|
|
|
|
const bool isFirstProxyShapeOfBody = mMapEntityToComponentIndex[entity] == srcIndex;
|
|
|
|
assert(isFirstProxyShapeOfBody || hasPreviousProxyShape(srcIndex));
|
|
|
|
// Copy the data of the source component to the destination location
|
|
new (mEntities + destIndex) Entity(mEntities[srcIndex]);
|
|
mProxyShapes[destIndex] = mProxyShapes[srcIndex];
|
|
new (mBroadPhaseIds + destIndex) int(mBroadPhaseIds[srcIndex]);
|
|
new (mLocalBounds + destIndex) AABB(mLocalBounds[srcIndex]);
|
|
new (mLocalToBodyTransforms + destIndex) Transform(mLocalToBodyTransforms[srcIndex]);
|
|
mCollisionShapes[destIndex] = mCollisionShapes[srcIndex];
|
|
new (mMasses + destIndex) decimal(mMasses[srcIndex]);
|
|
new (mPreviousBodyProxyShapes + destIndex) uint32(hasPreviousProxyShape(srcIndex) ? mPreviousBodyProxyShapes[srcIndex] : destIndex);
|
|
new (mNextBodyProxyShapes + destIndex) uint32(hasNextProxyShape(srcIndex) ? mNextBodyProxyShapes[srcIndex] : destIndex);
|
|
new (mCollisionCategoryBits + destIndex) unsigned short(mCollisionCategoryBits[srcIndex]);
|
|
new (mCollideWithMaskBits + destIndex) unsigned short(mCollideWithMaskBits[srcIndex]);
|
|
|
|
// Update the the next proxy-shape index of the previous proxy-shape
|
|
if (hasPreviousProxyShape(destIndex)) {
|
|
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[destIndex]] == srcIndex);
|
|
mNextBodyProxyShapes[mPreviousBodyProxyShapes[destIndex]] = destIndex;
|
|
}
|
|
|
|
// Update the the previous proxy-shape index of the next proxy-shape
|
|
if (hasNextProxyShape(destIndex)) {
|
|
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[destIndex]] == srcIndex);
|
|
mPreviousBodyProxyShapes[mNextBodyProxyShapes[destIndex]] = destIndex;
|
|
}
|
|
|
|
// Destroy the source component
|
|
destroyComponent(srcIndex);
|
|
|
|
// Update the entity to component index mapping if it is the first proxy-shape of the body
|
|
if (isFirstProxyShapeOfBody) {
|
|
|
|
mMapEntityToComponentIndex[entity] = destIndex;
|
|
assert(mMapEntityToComponentIndex[mEntities[destIndex]] == destIndex);
|
|
}
|
|
|
|
mMapProxyShapeToComponentIndex.add(Pair<const ProxyShape*, uint32>(mProxyShapes[destIndex], destIndex));
|
|
|
|
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[destIndex]] == destIndex || !hasNextProxyShape(destIndex));
|
|
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[destIndex]] == destIndex || !hasPreviousProxyShape(destIndex));
|
|
}
|
|
|
|
// Swap two components in the array
|
|
void ProxyShapesComponents::swapComponents(uint32 index1, uint32 index2) {
|
|
|
|
// Copy component 1 data
|
|
Entity entity1(mEntities[index1]);
|
|
ProxyShape* proxyShape1 = mProxyShapes[index1];
|
|
int broadPhaseId1 = mBroadPhaseIds[index1];
|
|
AABB localBounds1 = mLocalBounds[index1];
|
|
Transform localToBodyTransform1 = mLocalToBodyTransforms[index1];
|
|
CollisionShape* collisionShape1 = mCollisionShapes[index1];
|
|
decimal mass1 = mMasses[index1];
|
|
uint32 previousProxyShape1 = hasPreviousProxyShape(index1) ? mPreviousBodyProxyShapes[index1] : index2;
|
|
uint32 nextProxyShape1 = hasNextProxyShape(index1) ? mNextBodyProxyShapes[index1] : index2;
|
|
unsigned short collisionCategoryBits1 = mCollisionCategoryBits[index1];
|
|
unsigned short collideWithMaskBits1 = mCollideWithMaskBits[index1];
|
|
|
|
const bool isFirstBodyProxyShape1 = mMapEntityToComponentIndex[mEntities[index1]] == index1;
|
|
|
|
// Destroy component 1
|
|
destroyComponent(index1);
|
|
|
|
moveComponentToIndex(index2, index1);
|
|
|
|
// Reconstruct component 1 at component 2 location
|
|
new (mEntities + index2) Entity(entity1);
|
|
mProxyShapes[index2] = proxyShape1;
|
|
new (mBroadPhaseIds + index2) int(broadPhaseId1);
|
|
new (mLocalBounds + index2) AABB(localBounds1);
|
|
new (mLocalToBodyTransforms + index2) Transform(localToBodyTransform1);
|
|
mCollisionShapes[index2] = collisionShape1;
|
|
new (mMasses + index2) decimal(mass1);
|
|
new (mPreviousBodyProxyShapes + index2) uint32(previousProxyShape1);
|
|
new (mNextBodyProxyShapes + index2) uint32(nextProxyShape1);
|
|
new (mCollisionCategoryBits + index2) unsigned short(collisionCategoryBits1);
|
|
new (mCollideWithMaskBits + index2) unsigned short(collideWithMaskBits1);
|
|
|
|
// Update the the next proxy-shape index of the previous proxy-shape
|
|
if (hasPreviousProxyShape(index2)) {
|
|
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index2]] == index1);
|
|
mNextBodyProxyShapes[mPreviousBodyProxyShapes[index2]] = index2;
|
|
}
|
|
|
|
// Update the the previous proxy-shape index of the next proxy-shape
|
|
if (hasNextProxyShape(index2)) {
|
|
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index2]] == index1);
|
|
mPreviousBodyProxyShapes[mNextBodyProxyShapes[index2]] = index2;
|
|
}
|
|
|
|
mMapProxyShapeToComponentIndex.add(Pair<const ProxyShape*, uint32>(mProxyShapes[index2], index2));
|
|
|
|
// Update the entity to component index mapping if it is the first body proxy-shape
|
|
if (isFirstBodyProxyShape1) {
|
|
assert(!hasPreviousProxyShape(index2));
|
|
mMapEntityToComponentIndex[entity1] = index2;
|
|
}
|
|
|
|
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index1]] == index1 || !hasNextProxyShape(index1));
|
|
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index2]] == index2 || !hasNextProxyShape(index2));
|
|
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index1]] == index1 || !hasPreviousProxyShape(index1));
|
|
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index2]] == index2 || !hasPreviousProxyShape(index2));
|
|
}
|
|
|
|
// Remove a component at a given index
|
|
void ProxyShapesComponents::removeComponent(uint32 index) {
|
|
|
|
assert(index < mNbComponents);
|
|
|
|
// We want to keep the arrays tightly packed. Therefore, when a component is removed,
|
|
// we replace it with the last element of the array. But we need to make sure that sleeping
|
|
// and non-sleeping components stay grouped together.
|
|
|
|
// If the proxy-shape to destroy does not have a previous proxy-shape in the linked-list of proxy-shapes of its body
|
|
if (!hasPreviousProxyShape(index)) {
|
|
|
|
// Remove the mapping from entity to component index
|
|
mMapEntityToComponentIndex.remove(mEntities[index]);
|
|
|
|
// If the proxy-shape has a next proxy-shape in the linked-list
|
|
if (hasNextProxyShape(index)) {
|
|
|
|
assert(mEntities[index] == mEntities[mNextBodyProxyShapes[index]]);
|
|
|
|
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(mEntities[mNextBodyProxyShapes[index]], mNextBodyProxyShapes[index]));
|
|
}
|
|
}
|
|
|
|
// Update the linked-list of proxy-shapes of a body when a proxy-shape is removed
|
|
if (hasPreviousProxyShape(index)) {
|
|
|
|
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] == index);
|
|
assert(mEntities[index] == mEntities[mPreviousBodyProxyShapes[index]]);
|
|
|
|
// If the current proxy-shape to remove has a next proxy-shape in the linked-list
|
|
if (hasNextProxyShape(index)) {
|
|
|
|
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index);
|
|
|
|
// Make sure the next proxy-shape will follow the previous proxy-shape in the linked-list
|
|
mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] = mNextBodyProxyShapes[index];
|
|
}
|
|
else {
|
|
|
|
mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] = mPreviousBodyProxyShapes[index];
|
|
}
|
|
}
|
|
|
|
// Update the linked-list of proxy-shapes of a body when a proxy-shape is removed
|
|
if (hasNextProxyShape(index)) {
|
|
|
|
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index);
|
|
assert(mEntities[index] == mEntities[mNextBodyProxyShapes[index]]);
|
|
|
|
// If the current proxy-shape to remove has a previous proxy-shape in the linked-list
|
|
if (hasPreviousProxyShape(index)) {
|
|
|
|
// Make sure the previous proxy-shape will precede the next proxy-shape in the linked-list
|
|
mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] = mPreviousBodyProxyShapes[index];
|
|
}
|
|
else {
|
|
|
|
mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] = mNextBodyProxyShapes[index];
|
|
}
|
|
}
|
|
|
|
// Destroy the component
|
|
destroyComponent(index);
|
|
|
|
// If the component to remove is sleeping
|
|
if (index >= mSleepingStartIndex) {
|
|
|
|
// If the component is not the last one
|
|
if (index != mNbComponents - 1) {
|
|
|
|
// We replace it by the last sleeping component
|
|
moveComponentToIndex(mNbComponents - 1, index);
|
|
}
|
|
}
|
|
else { // If the component to remove is not sleeping
|
|
|
|
// If it not the last awake component
|
|
if (index != mSleepingStartIndex - 1) {
|
|
|
|
// We replace it by the last awake component
|
|
moveComponentToIndex(mSleepingStartIndex - 1, index);
|
|
}
|
|
|
|
// If there are sleeping components at the end
|
|
if (mSleepingStartIndex != mNbComponents) {
|
|
|
|
// We replace the last awake component by the last sleeping component
|
|
moveComponentToIndex(mNbComponents - 1, mSleepingStartIndex - 1);
|
|
}
|
|
|
|
mSleepingStartIndex--;
|
|
}
|
|
|
|
assert(mSleepingStartIndex <= mNbComponents);
|
|
mNbComponents--;
|
|
}
|
|
|
|
// Return true if a given proxy-shape component has a previous proxy-shape in the linked-list of proxy-shapes of a body
|
|
bool ProxyShapesComponents::hasPreviousProxyShape(uint32 index) const {
|
|
assert(index < mNbComponents);
|
|
return mPreviousBodyProxyShapes[index] != index;
|
|
}
|
|
|
|
// Return true if a given proxy-shape component has a next proxy-shape in the linked-list of proxy-shapes of a body
|
|
bool ProxyShapesComponents::hasNextProxyShape(uint32 index) const {
|
|
assert(index < mNbComponents);
|
|
return mNextBodyProxyShapes[index] != index;
|
|
}
|
|
|
|
// Destroy a component at a given index
|
|
void ProxyShapesComponents::destroyComponent(uint32 index) {
|
|
|
|
assert(index < mNbComponents);
|
|
|
|
mMapProxyShapeToComponentIndex.remove(mProxyShapes[index]);
|
|
|
|
mEntities[index].~Entity();
|
|
mProxyShapes[index] = nullptr;
|
|
mLocalBounds[index].~AABB();
|
|
mLocalToBodyTransforms[index].~Transform();
|
|
mCollisionShapes[index] = nullptr;
|
|
}
|
|
|
|
// Notify if a given entity is sleeping or not
|
|
void ProxyShapesComponents::setIsEntitySleeping(Entity entity, bool isSleeping) {
|
|
|
|
const uint32 index = mMapEntityToComponentIndex[entity];
|
|
|
|
// If the component was sleeping and is not sleeping anymore
|
|
if (!isSleeping && index >= mSleepingStartIndex) {
|
|
|
|
assert(mSleepingStartIndex < mNbComponents);
|
|
|
|
// If the sleeping component is not the first sleeping component
|
|
if (mSleepingStartIndex != index) {
|
|
|
|
// Swap the first sleeping component with the one we need to wake up
|
|
swapComponents(index, mSleepingStartIndex);
|
|
}
|
|
|
|
mSleepingStartIndex++;
|
|
}
|
|
// If the component was awake and must now go to sleep
|
|
else if (isSleeping && index < mSleepingStartIndex) {
|
|
|
|
assert(mSleepingStartIndex > 0);
|
|
|
|
// If the awake component is not the only awake component
|
|
if (index != mSleepingStartIndex - 1) {
|
|
|
|
// Swap the last awake component with the one we need to put to sleep
|
|
swapComponents(index, mSleepingStartIndex - 1);
|
|
}
|
|
|
|
mSleepingStartIndex--;
|
|
}
|
|
|
|
assert(mSleepingStartIndex <= mNbComponents);
|
|
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index || !hasNextProxyShape(index));
|
|
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] == index || !hasPreviousProxyShape(index));
|
|
}
|
|
|
|
// Remove all the components of a given entity
|
|
void ProxyShapesComponents::removeComponents(Entity entity) {
|
|
|
|
auto it = mMapEntityToComponentIndex.find(entity);
|
|
|
|
// While there are components for this entity
|
|
while (it != mMapEntityToComponentIndex.end()) {
|
|
|
|
// Remove the component
|
|
removeComponent(it->second);
|
|
|
|
it = mMapEntityToComponentIndex.find(entity);
|
|
}
|
|
|
|
assert(!mMapEntityToComponentIndex.containsKey(entity));
|
|
}
|
|
|
|
// Remove a given proxy-shape
|
|
void ProxyShapesComponents::removeComponent(const ProxyShape* proxyShape) {
|
|
|
|
uint32 index = mMapProxyShapeToComponentIndex[proxyShape];
|
|
|
|
removeComponent(index);
|
|
}
|