Liquidfun links

This commit is contained in:
viktorljung
2015-09-09 18:04:17 +01:00
parent 8833377855
commit 67f7a30ca6
184 changed files with 52115 additions and 2 deletions
+225
View File
@@ -0,0 +1,225 @@
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
* Copyright (c) 2013 Google, Inc.
*
* 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.
*/
#include <Box2D/Common/b2BlockAllocator.h>
#include <limits.h>
#include <memory.h>
#include <stddef.h>
#include <string.h>
#include <new> // For placement new
int32 b2BlockAllocator::s_blockSizes[b2_blockSizes] =
{
16, // 0
32, // 1
64, // 2
96, // 3
128, // 4
160, // 5
192, // 6
224, // 7
256, // 8
320, // 9
384, // 10
448, // 11
512, // 12
640, // 13
};
uint8 b2BlockAllocator::s_blockSizeLookup[b2_maxBlockSize + 1];
bool b2BlockAllocator::s_blockSizeLookupInitialized;
struct b2Chunk
{
int32 blockSize;
b2Block* blocks;
};
struct b2Block
{
b2Block* next;
};
b2BlockAllocator::b2BlockAllocator()
{
b2Assert((uint32)b2_blockSizes < UCHAR_MAX);
m_chunkSpace = b2_chunkArrayIncrement;
m_chunkCount = 0;
m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk));
memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk));
memset(m_freeLists, 0, sizeof(m_freeLists));
if (s_blockSizeLookupInitialized == false)
{
int32 j = 0;
for (int32 i = 1; i <= b2_maxBlockSize; ++i)
{
b2Assert(j < b2_blockSizes);
if (i <= s_blockSizes[j])
{
s_blockSizeLookup[i] = (uint8)j;
}
else
{
++j;
s_blockSizeLookup[i] = (uint8)j;
}
}
s_blockSizeLookupInitialized = true;
}
}
b2BlockAllocator::~b2BlockAllocator()
{
for (int32 i = 0; i < m_chunkCount; ++i)
{
b2Free(m_chunks[i].blocks);
}
b2Free(m_chunks);
}
uint32 b2BlockAllocator::GetNumGiantAllocations() const
{
return m_giants.GetList().GetLength();
}
void* b2BlockAllocator::Allocate(int32 size)
{
if (size == 0)
return NULL;
b2Assert(0 < size);
if (size > b2_maxBlockSize)
{
return m_giants.Allocate(size);
}
int32 index = s_blockSizeLookup[size];
b2Assert(0 <= index && index < b2_blockSizes);
if (m_freeLists[index])
{
b2Block* block = m_freeLists[index];
m_freeLists[index] = block->next;
return block;
}
else
{
if (m_chunkCount == m_chunkSpace)
{
b2Chunk* oldChunks = m_chunks;
m_chunkSpace += b2_chunkArrayIncrement;
m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk));
memcpy(m_chunks, oldChunks, m_chunkCount * sizeof(b2Chunk));
memset(m_chunks + m_chunkCount, 0, b2_chunkArrayIncrement * sizeof(b2Chunk));
b2Free(oldChunks);
}
b2Chunk* chunk = m_chunks + m_chunkCount;
chunk->blocks = (b2Block*)b2Alloc(b2_chunkSize);
#if DEBUG
memset(chunk->blocks, 0xcd, b2_chunkSize);
#endif
int32 blockSize = s_blockSizes[index];
chunk->blockSize = blockSize;
int32 blockCount = b2_chunkSize / blockSize;
b2Assert(blockCount * blockSize <= b2_chunkSize);
for (int32 i = 0; i < blockCount - 1; ++i)
{
b2Block* block = (b2Block*)((int8*)chunk->blocks + blockSize * i);
b2Block* next = (b2Block*)((int8*)chunk->blocks + blockSize * (i + 1));
block->next = next;
}
b2Block* last = (b2Block*)((int8*)chunk->blocks + blockSize * (blockCount - 1));
last->next = NULL;
m_freeLists[index] = chunk->blocks->next;
++m_chunkCount;
return chunk->blocks;
}
}
void b2BlockAllocator::Free(void* p, int32 size)
{
if (size == 0)
{
return;
}
b2Assert(0 < size);
if (size > b2_maxBlockSize)
{
m_giants.Free(p);
return;
}
int32 index = s_blockSizeLookup[size];
b2Assert(0 <= index && index < b2_blockSizes);
#if B2_ASSERT_ENABLED
// Verify the memory address and size is valid.
int32 blockSize = s_blockSizes[index];
bool found = false;
for (int32 i = 0; i < m_chunkCount; ++i)
{
b2Chunk* chunk = m_chunks + i;
if (chunk->blockSize != blockSize)
{
b2Assert( (int8*)p + blockSize <= (int8*)chunk->blocks ||
(int8*)chunk->blocks + b2_chunkSize <= (int8*)p);
}
else
{
if ((int8*)chunk->blocks <= (int8*)p && (int8*)p + blockSize <= (int8*)chunk->blocks + b2_chunkSize)
{
found = true;
}
}
}
b2Assert(found);
#endif // B2_ASSERT_ENABLED
#if DEBUG
memset(p, 0xfd, s_blockSizes[index]);
#endif
b2Block* block = (b2Block*)p;
block->next = m_freeLists[index];
m_freeLists[index] = block;
}
void b2BlockAllocator::Clear()
{
for (int32 i = 0; i < m_chunkCount; ++i)
{
b2Free(m_chunks[i].blocks);
}
m_chunkCount = 0;
memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk));
memset(m_freeLists, 0, sizeof(m_freeLists));
}
+68
View File
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
*
* 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.
*/
#ifndef B2_BLOCK_ALLOCATOR_H
#define B2_BLOCK_ALLOCATOR_H
#include <Box2D/Common/b2Settings.h>
#include <Box2D/Common/b2TrackedBlock.h>
const int32 b2_chunkSize = 16 * 1024;
const int32 b2_maxBlockSize = 640;
const int32 b2_blockSizes = 14;
const int32 b2_chunkArrayIncrement = 128;
struct b2Block;
struct b2Chunk;
/// This is a small object allocator used for allocating small
/// objects that persist for more than one time step.
/// See: http://www.codeproject.com/useritems/Small_Block_Allocator.asp
class b2BlockAllocator
{
public:
b2BlockAllocator();
~b2BlockAllocator();
/// Allocate memory. This uses b2Alloc if the size is larger than b2_maxBlockSize.
void* Allocate(int32 size);
/// Free memory. This uses b2Free if the size is larger than b2_maxBlockSize.
void Free(void* p, int32 size);
void Clear();
/// Returns the number of allocations larger than the max block size.
uint32 GetNumGiantAllocations() const;
private:
b2Chunk* m_chunks;
int32 m_chunkCount;
int32 m_chunkSpace;
b2Block* m_freeLists[b2_blockSizes];
// Record giant allocations--ones bigger than the max block size
b2TrackedBlockAllocator m_giants;
static int32 s_blockSizes[b2_blockSizes];
static uint8 s_blockSizeLookup[b2_maxBlockSize + 1];
static bool s_blockSizeLookupInitialized;
};
#endif
+44
View File
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2011 Erin Catto http://box2d.org
*
* 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.
*/
#include <Box2D/Common/b2Draw.h>
b2Draw::b2Draw()
{
m_drawFlags = 0;
}
void b2Draw::SetFlags(uint32 flags)
{
m_drawFlags = flags;
}
uint32 b2Draw::GetFlags() const
{
return m_drawFlags;
}
void b2Draw::AppendFlags(uint32 flags)
{
m_drawFlags |= flags;
}
void b2Draw::ClearFlags(uint32 flags)
{
m_drawFlags &= ~flags;
}
+92
View File
@@ -0,0 +1,92 @@
/*
* Copyright (c) 2011 Erin Catto http://box2d.org
* Copyright (c) 2014 Google, Inc.
*
* 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.
*/
#ifndef B2_DRAW_H
#define B2_DRAW_H
#include <Box2D/Common/b2Math.h>
#include <Box2D/Particle/b2Particle.h>
/// Color for debug drawing. Each value has the range [0,1].
struct b2Color
{
b2Color() {}
b2Color(float32 r, float32 g, float32 b) : r(r), g(g), b(b) {}
void Set(float32 ri, float32 gi, float32 bi) { r = ri; g = gi; b = bi; }
float32 r, g, b;
};
/// Implement and register this class with a b2World to provide debug drawing of physics
/// entities in your game.
class b2Draw
{
public:
b2Draw();
virtual ~b2Draw() {}
enum
{
e_shapeBit = 0x0001, ///< draw shapes
e_jointBit = 0x0002, ///< draw joint connections
e_aabbBit = 0x0004, ///< draw axis aligned bounding boxes
e_pairBit = 0x0008, ///< draw broad-phase pairs
e_centerOfMassBit = 0x0010, ///< draw center of mass frame
e_particleBit = 0x0020 ///< draw particles
};
/// Set the drawing flags.
void SetFlags(uint32 flags);
/// Get the drawing flags.
uint32 GetFlags() const;
/// Append flags to the current flags.
void AppendFlags(uint32 flags);
/// Clear flags from the current flags.
void ClearFlags(uint32 flags);
/// Draw a closed polygon provided in CCW order.
virtual void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) = 0;
/// Draw a solid closed polygon provided in CCW order.
virtual void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) = 0;
/// Draw a circle.
virtual void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color) = 0;
/// Draw a solid circle.
virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) = 0;
/// Draw a particle array
virtual void DrawParticles(const b2Vec2 *centers, float32 radius, const b2ParticleColor *colors, int32 count) = 0;
/// Draw a line segment.
virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) = 0;
/// Draw a transform. Choose your own length scale.
/// @param xf a transform.
virtual void DrawTransform(const b2Transform& xf) = 0;
protected:
uint32 m_drawFlags;
};
#endif
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2014 Google, Inc.
*
* 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.
*/
#include <Box2D/Common/b2FreeList.h>
#include <Box2D/Common/b2IntrusiveList.h>
#include <Box2D/Common/b2Settings.h>
/// Allocate an item from the freelist.
b2IntrusiveListNode* b2FreeList::Allocate()
{
if (m_free.IsEmpty()) return NULL;
b2IntrusiveListNode * const node = m_free.GetNext();
node->Remove();
m_allocated.InsertBefore(node);
return node;
}
void b2FreeList::Free(b2IntrusiveListNode* node)
{
b2Assert(node);
#if B2_FREE_LIST_CHECK_ALLOCATED_ON_FREE
b2Assert(m_allocated.FindNodeInList(node));
#endif // B2_FREE_LIST_CHECK_ALLOCATED_ON_FREE
node->Remove();
m_free.InsertAfter(node);
}
void b2FreeList::AddToFreeList(b2IntrusiveListNode* node)
{
b2Assert(node);
b2Assert(!node->InList());
m_free.InsertBefore(node);
}
void b2FreeList::RemoveAll()
{
while (!m_allocated.IsEmpty()) {
m_allocated.GetNext()->Remove();
}
while (!m_free.IsEmpty()) {
m_free.GetNext()->Remove();
}
}
+113
View File
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2014 Google, Inc.
*
* 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.
*/
#ifndef B2_FREE_LIST_H
#define B2_FREE_LIST_H
#include <Box2D/Common/b2IntrusiveList.h>
#include <Box2D/Common/b2Settings.h>
/// When B2_FREE_LIST_CHECK_ALLOCATED_ON_FREE is 1, b2FreeList::Free() will
/// check that the deallocated node was allocated from the freelist.
#ifndef B2_FREE_LIST_CHECK_ALLOCATED_ON_FREE
#define B2_FREE_LIST_CHECK_ALLOCATED_ON_FREE 0
#endif // B2_FREE_LIST_CHECK_ALLOCATED_ON_FREE
/// Fast - O(1) - list based allocator for items that can be inserted into
/// b2IntrusiveListNode lists.
class b2FreeList
{
public:
/// Construct the free list.
b2FreeList() { }
/// Destroy the free list.
~b2FreeList() { }
/// Allocate an item from the freelist.
b2IntrusiveListNode* Allocate();
/// Free an item from the freelist.
void Free(b2IntrusiveListNode* node);
/// Add an item to the freelist so that it can be allocated using
/// b2FreeList::Allocate().
void AddToFreeList(b2IntrusiveListNode* node);
/// Remove all items (allocated and free) from the freelist.
void RemoveAll();
/// Get the list which tracks allocated items.
const b2IntrusiveListNode& GetAllocatedList() const {
return m_allocated;
}
/// Get the list which tracks free items.
const b2IntrusiveListNode& GetFreeList() const {
return m_free;
}
protected:
/// List of allocated items.
b2IntrusiveListNode m_allocated;
/// List of free items.
b2IntrusiveListNode m_free;
};
/// Typed b2FreeList which manages items of type T assuming T implements
/// the GetInstanceFromListNode() and GetListNode() methods.
template<typename T>
class b2TypedFreeList {
public:
/// Construct the free list.
b2TypedFreeList() { }
/// Destroy the free list.
~b2TypedFreeList() { }
/// Allocate an item from the free list.
T* Allocate() {
b2IntrusiveListNode* const node = m_freeList.Allocate();
if (!node) return NULL;
return T::GetInstanceFromListNode(node);
}
/// Free an item.
void Free(T* instance) {
b2Assert(instance);
m_freeList.Free(instance->GetListNode());
}
/// Add an item to the freelist so that it can be allocated with
/// b2TypedFreeList::Allocate().
void AddToFreeList(T* instance)
{
b2Assert(instance);
m_freeList.AddToFreeList(instance->GetListNode());
}
// Get the underlying b2FreeList.
b2FreeList* GetFreeList() { return &m_freeList; }
const b2FreeList* GetFreeList() const { return &m_freeList; }
protected:
b2FreeList m_freeList;
};
#endif // B2_FREE_LIST_H
+200
View File
@@ -0,0 +1,200 @@
/*
* Copyright (c) 2014 Google, Inc.
*
* 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.
*/
#ifndef B2_GROWABLE_BUFFER_H
#define B2_GROWABLE_BUFFER_H
#include <Box2D/Common/b2BlockAllocator.h>
#include <string.h>
#include <memory.h>
#include <algorithm>
/// A simple array-like container, similar to std::vector.
/// If we ever start using stl, we should replace this with std::vector.
template <typename T>
class b2GrowableBuffer
{
public:
b2GrowableBuffer(b2BlockAllocator& allocator) :
data(NULL),
count(0),
capacity(0),
allocator(&allocator)
{
#if defined(LIQUIDFUN_SIMD_NEON)
// b2ParticleAssembly.neon.s assumes these values are at fixed offsets.
// If this assert fails, be sure to update the assembly offsets!
// ldr r3, [r9, #0] @ r3 = out = contacts.data
// ldr r6, [r9, #8] @ r6 = contacts.capacity
b2Assert((intptr_t)&data - (intptr_t)(this) == 0
&& (intptr_t)&capacity - (intptr_t)(this) == 8);
#endif // defined(LIQUIDFUN_SIMD_NEON)
}
b2GrowableBuffer(const b2GrowableBuffer<T>& rhs) :
data(NULL),
count(rhs.count),
capacity(rhs.capacity),
allocator(rhs.allocator)
{
if (rhs.data != NULL)
{
data = (T*) allocator->Allocate(sizeof(T) * capacity);
memcpy(data, rhs.data, sizeof(T) * count);
}
}
~b2GrowableBuffer()
{
Free();
}
T& Append()
{
if (count >= capacity)
{
Grow();
}
return data[count++];
}
void Reserve(int32 newCapacity)
{
if (capacity >= newCapacity)
return;
// Reallocate and copy.
T* newData = (T*) allocator->Allocate(sizeof(T) * newCapacity);
if (data)
{
memcpy(newData, data, sizeof(T) * count);
allocator->Free(data, sizeof(T) * capacity);
}
// Update pointer and capacity.
capacity = newCapacity;
data = newData;
}
void Grow()
{
// Double the capacity.
int32 newCapacity = capacity ? 2 * capacity
: b2_minParticleSystemBufferCapacity;
b2Assert(newCapacity > capacity);
Reserve(newCapacity);
}
void Free()
{
if (data == NULL)
return;
allocator->Free(data, sizeof(data[0]) * capacity);
data = NULL;
capacity = 0;
count = 0;
}
void Shorten(const T* newEnd)
{
b2Assert(newEnd >= data);
count = (int32) (newEnd - data);
}
T& operator[](int i)
{
return data[i];
}
const T& operator[](int i) const
{
return data[i];
}
T* Data()
{
return data;
}
const T* Data() const
{
return data;
}
T* Begin()
{
return data;
}
const T* Begin() const
{
return data;
}
T* End()
{
return &data[count];
}
const T* End() const
{
return &data[count];
}
int32 GetCount() const
{
return count;
}
void SetCount(int32 newCount)
{
b2Assert(0 <= newCount && newCount <= capacity);
count = newCount;
}
int32 GetCapacity() const
{
return capacity;
}
template<class UnaryPredicate>
T* RemoveIf(UnaryPredicate pred)
{
T* newEnd = std::remove_if(data, data + count, pred);
Shorten(newEnd);
return newEnd;
}
template<class BinaryPredicate>
T* Unique(BinaryPredicate pred)
{
T* newEnd = std::unique(data, data + count, pred);
Shorten(newEnd);
return newEnd;
}
private:
T* data;
int32 count;
int32 capacity;
b2BlockAllocator* allocator;
};
#endif // B2_GROWABLE_BUFFER_H
+87
View File
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2010 Erin Catto http://www.box2d.org
*
* 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.
*/
#ifndef B2_GROWABLE_STACK_H
#define B2_GROWABLE_STACK_H
#include <Box2D/Common/b2Settings.h>
#include <string.h>
#include <memory.h>
/// This is a growable LIFO stack with an initial capacity of N.
/// If the stack size exceeds the initial capacity, the heap is used
/// to increase the size of the stack.
template <typename T, int32 N>
class b2GrowableStack
{
public:
b2GrowableStack()
{
m_stack = m_array;
m_count = 0;
m_capacity = N;
}
~b2GrowableStack()
{
if (m_stack != m_array)
{
b2Free(m_stack);
m_stack = NULL;
}
}
void Push(const T& element)
{
if (m_count == m_capacity)
{
T* old = m_stack;
m_capacity *= 2;
m_stack = (T*)b2Alloc(m_capacity * sizeof(T));
memcpy(m_stack, old, m_count * sizeof(T));
if (old != m_array)
{
b2Free(old);
}
}
m_stack[m_count] = element;
++m_count;
}
T Pop()
{
b2Assert(m_count > 0);
--m_count;
return m_stack[m_count];
}
int32 GetCount()
{
return m_count;
}
private:
T* m_stack;
T m_array[N];
int32 m_count;
int32 m_capacity;
};
#endif
+369
View File
@@ -0,0 +1,369 @@
/*
* Copyright (c) 2014 Google, Inc.
*
* 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.
*/
#ifndef B2_INTRUSIVE_LIST
#define B2_INTRUSIVE_LIST
#include <Box2D/Common/b2Settings.h>
// Whether to enable b2IntrusiveList::ValidateList().
// Be careful when enabling this since this changes the size of
// b2IntrusiveListNode so make sure *all* projects that include Box2D.h
// also define this value in the same way to avoid data corruption.
#ifndef B2_INTRUSIVE_LIST_VALIDATE
#define B2_INTRUSIVE_LIST_VALIDATE 0
#endif // B2_INTRUSIVE_LIST_VALIDATE
/// b2IntrusiveListNode is used to implement an intrusive doubly-linked
/// list.
///
/// For example:
///
/// class MyClass {
/// public:
/// MyClass(const char *msg) : m_msg(msg) {}
/// const char* GetMessage() const { return m_msg; }
/// B2_INTRUSIVE_LIST_GET_NODE(m_node);
/// B2_INTRUSIVE_LIST_NODE_GET_CLASS(MyClass, m_node);
/// private:
/// b2IntrusiveListNode m_node;
/// const char *m_msg;
/// };
///
/// int main(int argc, char *argv[]) {
/// b2IntrusiveListNode list; // NOTE: type is NOT MyClass
/// MyClass a("this");
/// MyClass b("is");
/// MyClass c("a");
/// MyClass d("test");
/// list.InsertBefore(a.GetListNode());
/// list.InsertBefore(b.GetListNode());
/// list.InsertBefore(c.GetListNode());
/// list.InsertBefore(d.GetListNode());
/// for (b2IntrusiveListNode* node = list.GetNext();
/// node != list.GetTerminator(); node = node->GetNext()) {
/// MyClass *cls = MyClass::GetInstanceFromListNode(node);
/// printf("%s\n", cls->GetMessage());
/// }
/// return 0;
/// }
class b2IntrusiveListNode
{
public:
/// Initialize the node.
b2IntrusiveListNode()
{
Initialize();
#if B2_INTRUSIVE_LIST_VALIDATE
m_magic = k_magic;
#endif // B2_INTRUSIVE_LIST_VALIDATE
}
/// If the node is in a list, remove it from the list.
~b2IntrusiveListNode()
{
Remove();
#if B2_INTRUSIVE_LIST_VALIDATE
m_magic = 0;
#endif // B2_INTRUSIVE_LIST_VALIDATE
}
/// Insert this node after the specified node.
void InsertAfter(b2IntrusiveListNode* const node)
{
b2Assert(!node->InList());
node->m_next = m_next;
node->m_prev = this;
m_next->m_prev = node;
m_next = node;
}
/// Insert this node before the specified node.
void InsertBefore(b2IntrusiveListNode* const node)
{
b2Assert(!node->InList());
node->m_next = this;
node->m_prev = m_prev;
m_prev->m_next = node;
m_prev = node;
}
/// Get the terminator of the list.
const b2IntrusiveListNode* GetTerminator() const
{
return this;
}
/// Remove this node from the list it's currently in.
b2IntrusiveListNode* Remove()
{
m_prev->m_next = m_next;
m_next->m_prev = m_prev;
Initialize();
return this;
}
/// Determine whether this list is empty or the node isn't in a list.
bool IsEmpty() const
{
return GetNext() == this;
}
/// Determine whether this node is in a list or the list contains nodes.
bool InList() const
{
return !IsEmpty();
}
/// Calculate the length of the list.
uint32 GetLength() const
{
uint32 length = 0;
const b2IntrusiveListNode * const terminator = GetTerminator();
for (const b2IntrusiveListNode* node = GetNext();
node != terminator; node = node->GetNext())
{
length++;
}
return length;
}
/// Get the next node in the list.
b2IntrusiveListNode* GetNext() const
{
return m_next;
}
/// Get the previous node in the list.
b2IntrusiveListNode* GetPrevious() const
{
return m_prev;
}
/// If B2_INTRUSIVE_LIST_VALIDATE is 1 perform a very rough validation
/// of all nodes in the list.
bool ValidateList() const
{
#if B2_INTRUSIVE_LIST_VALIDATE
if (m_magic != k_magic) return false;
const b2IntrusiveListNode * const terminator = GetTerminator();
for (b2IntrusiveListNode *node = GetNext(); node != terminator;
node = node->GetNext()) {
if (node->m_magic != k_magic) return false;
}
#endif // B2_INTRUSIVE_LIST_VALIDATE
return true;
}
/// Determine whether the specified node is present in this list.
bool FindNodeInList(b2IntrusiveListNode* const nodeToFind) const
{
const b2IntrusiveListNode * const terminator = GetTerminator();
for (b2IntrusiveListNode *node = GetNext(); node != terminator;
node = node->GetNext())
{
if (nodeToFind == node) return true;
}
return false;
}
private:
/// Initialize the list node.
void Initialize()
{
m_next = this;
m_prev = this;
}
private:
#if B2_INTRUSIVE_LIST_VALIDATE
uint32 m_magic;
#endif // B2_INTRUSIVE_LIST_VALIDATE
/// The next node in the list.
b2IntrusiveListNode *m_prev;
/// The previous node in the list.
b2IntrusiveListNode *m_next;
private:
#if B2_INTRUSIVE_LIST_VALIDATE
static const uint32 k_magic = 0x7157ac01;
#endif // B2_INTRUSIVE_LIST_VALIDATE
};
/// Declares the member function GetListNode() of Class to retrieve a pointer
/// to NodeMemberName.
/// See #B2_INTRUSIVE_LIST_NODE_GET_CLASS_ACCESSOR()
#define B2_INTRUSIVE_LIST_GET_NODE(NodeMemberName) \
b2IntrusiveListNode* GetListNode() { return &NodeMemberName; } \
const b2IntrusiveListNode* GetListNode() const { return &NodeMemberName; }
/// Declares the member function FunctionName of Class to retrieve a pointer
/// to a Class instance from a list node pointer. NodeMemberName references
/// the name of the b2IntrusiveListNode member of Class.
#define B2_INTRUSIVE_LIST_NODE_GET_CLASS_ACCESSOR( \
Class, NodeMemberName, FunctionName) \
static Class* FunctionName(b2IntrusiveListNode *node) \
{ \
Class *cls = NULL; \
/* This effectively performs offsetof(Class, NodeMemberName) */ \
/* which ends up in the undefined behavior realm of C++ but in */ \
/* practice this works with most compilers. */ \
return reinterpret_cast<Class*>((uint8*)(node) - \
(uint8*)(&cls->NodeMemberName)); \
} \
\
static const Class* FunctionName(const b2IntrusiveListNode *node) \
{ \
return FunctionName(const_cast<b2IntrusiveListNode*>(node)); \
}
/// Declares the member function GetInstanceFromListNode() of Class to retrieve
/// a pointer to a Class instance from a list node pointer. NodeMemberName
/// reference the name of the b2IntrusiveListNode member of Class.
#define B2_INTRUSIVE_LIST_NODE_GET_CLASS(Class, NodeMemberName) \
B2_INTRUSIVE_LIST_NODE_GET_CLASS_ACCESSOR(Class, NodeMemberName, \
GetInstanceFromListNode)
/// b2TypedIntrusiveListNode which supports inserting an object into a single
/// doubly linked list. For objects that need to be inserted in multiple
/// doubly linked lists, use b2IntrusiveListNode.
///
/// For example:
///
/// class IntegerItem : public b2TypedIntrusiveListNode<IntegerItem>
/// {
/// public:
/// IntegerItem(int32 value) : m_value(value) { }
/// ~IntegerItem() { }
/// int32 GetValue() const { return m_value; }
/// private:
/// int32 m_value;
/// };
///
/// int main(int argc, const char *arvg[]) {
/// b2TypedIntrusiveListNode<IntegerItem> list;
/// IntegerItem a(1);
/// IntegerItem b(2);
/// IntegerItem c(3);
/// list.InsertBefore(&a);
/// list.InsertBefore(&b);
/// list.InsertBefore(&c);
/// for (IntegerItem* item = list.GetNext();
/// item != list.GetTerminator(); item = item->GetNext())
/// {
/// printf("%d\n", item->GetValue());
/// }
/// }
template<typename T>
class b2TypedIntrusiveListNode
{
public:
b2TypedIntrusiveListNode() { }
~b2TypedIntrusiveListNode() { }
/// Insert this object after the specified object.
void InsertAfter(T* const obj)
{
b2Assert(obj);
GetListNode()->InsertAfter(obj->GetListNode());
}
/// Insert this object before the specified object.
void InsertBefore(T* const obj)
{
b2Assert(obj);
GetListNode()->InsertBefore(obj->GetListNode());
}
/// Get the next object in the list.
/// Check against GetTerminator() before deferencing the object.
T* GetNext() const
{
return GetInstanceFromListNode(GetListNode()->GetNext());
}
/// Get the previous object in the list.
/// Check against GetTerminator() before deferencing the object.
T* GetPrevious() const
{
return GetInstanceFromListNode(GetListNode()->GetPrevious());
}
/// Get the terminator of the list.
/// This should not be dereferenced as it is a pointer to
/// b2TypedIntrusiveListNode<T> *not* T.
T* GetTerminator() const
{
return (T*)GetListNode();
}
/// Remove this object from the list it's currently in.
T* Remove()
{
GetListNode()->Remove();
return GetInstanceFromListNode(GetListNode());
}
/// Determine whether this object is in a list.
bool InList() const
{
return GetListNode()->InList();
}
// Determine whether this list is empty.
bool IsEmpty() const
{
return GetListNode()->IsEmpty();
}
/// Calculate the length of the list.
uint32 GetLength() const
{
return GetListNode()->GetLength();
}
B2_INTRUSIVE_LIST_GET_NODE(m_node);
private:
// Node within an intrusive list.
b2IntrusiveListNode m_node;
public:
/// Get a pointer to the instance of T that contains "node".
static T* GetInstanceFromListNode(b2IntrusiveListNode* const node)
{
b2Assert(node);
// Calculate the pointer to T from the offset.
return (T*)((uint8*)node - GetNodeOffset(node));
}
private:
// Get the offset of m_node within this class.
static int32 GetNodeOffset(b2IntrusiveListNode* const node)
{
b2Assert(node);
// Perform some type punning to calculate the offset of m_node in T.
// WARNING: This could result in undefined behavior with some C++
// compilers.
T* obj = (T*)node;
int32 nodeOffset = (int32)((uint8*)&obj->m_node - (uint8*)obj);
return nodeOffset;
}
};
#endif // B2_INTRUSIVE_LIST
+94
View File
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2007-2009 Erin Catto http://www.box2d.org
*
* 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.
*/
#include <Box2D/Common/b2Math.h>
const b2Vec2 b2Vec2_zero(0.0f, 0.0f);
/// Solve A * x = b, where b is a column vector. This is more efficient
/// than computing the inverse in one-shot cases.
b2Vec3 b2Mat33::Solve33(const b2Vec3& b) const
{
float32 det = b2Dot(ex, b2Cross(ey, ez));
if (det != 0.0f)
{
det = 1.0f / det;
}
b2Vec3 x;
x.x = det * b2Dot(b, b2Cross(ey, ez));
x.y = det * b2Dot(ex, b2Cross(b, ez));
x.z = det * b2Dot(ex, b2Cross(ey, b));
return x;
}
/// Solve A * x = b, where b is a column vector. This is more efficient
/// than computing the inverse in one-shot cases.
b2Vec2 b2Mat33::Solve22(const b2Vec2& b) const
{
float32 a11 = ex.x, a12 = ey.x, a21 = ex.y, a22 = ey.y;
float32 det = a11 * a22 - a12 * a21;
if (det != 0.0f)
{
det = 1.0f / det;
}
b2Vec2 x;
x.x = det * (a22 * b.x - a12 * b.y);
x.y = det * (a11 * b.y - a21 * b.x);
return x;
}
///
void b2Mat33::GetInverse22(b2Mat33* M) const
{
float32 a = ex.x, b = ey.x, c = ex.y, d = ey.y;
float32 det = a * d - b * c;
if (det != 0.0f)
{
det = 1.0f / det;
}
M->ex.x = det * d; M->ey.x = -det * b; M->ex.z = 0.0f;
M->ex.y = -det * c; M->ey.y = det * a; M->ey.z = 0.0f;
M->ez.x = 0.0f; M->ez.y = 0.0f; M->ez.z = 0.0f;
}
/// Returns the zero matrix if singular.
void b2Mat33::GetSymInverse33(b2Mat33* M) const
{
float32 det = b2Dot(ex, b2Cross(ey, ez));
if (det != 0.0f)
{
det = 1.0f / det;
}
float32 a11 = ex.x, a12 = ey.x, a13 = ez.x;
float32 a22 = ey.y, a23 = ez.y;
float32 a33 = ez.z;
M->ex.x = det * (a22 * a33 - a23 * a23);
M->ex.y = det * (a13 * a23 - a12 * a33);
M->ex.z = det * (a12 * a23 - a13 * a22);
M->ey.x = M->ex.y;
M->ey.y = det * (a11 * a33 - a13 * a13);
M->ey.z = det * (a13 * a12 - a11 * a23);
M->ez.x = M->ex.z;
M->ez.y = M->ey.z;
M->ez.z = det * (a11 * a22 - a12 * a12);
}
+800
View File
@@ -0,0 +1,800 @@
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
*
* 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.
*/
#ifndef B2_MATH_H
#define B2_MATH_H
#include <Box2D/Common/b2Settings.h>
#include <math.h>
/// This function is used to ensure that a floating point number is not a NaN or infinity.
inline bool b2IsValid(float32 x)
{
union {
float32 f;
int32 i;
} v = { x };
return (v.i & 0x7f800000) != 0x7f800000;
}
/// This is a approximate yet fast inverse square-root.
inline float32 b2InvSqrt(float32 x)
{
union
{
float32 x;
int32 i;
} convert;
convert.x = x;
float32 xhalf = 0.5f * x;
convert.i = 0x5f3759df - (convert.i >> 1);
x = convert.x;
x = x * (1.5f - xhalf * x * x);
return x;
}
#define b2Sqrt(x) sqrtf(x)
#define b2Atan2(y, x) atan2f(y, x)
/// A 2D column vector.
struct b2Vec2
{
/// Default constructor does nothing (for performance).
b2Vec2() {}
/// Construct using coordinates.
b2Vec2(float32 x, float32 y) : x(x), y(y) {}
/// Set this vector to all zeros.
void SetZero() { x = 0.0f; y = 0.0f; }
/// Set this vector to some specified coordinates.
void Set(float32 x_, float32 y_) { x = x_; y = y_; }
/// Negate this vector.
b2Vec2 operator -() const { b2Vec2 v; v.Set(-x, -y); return v; }
/// Read from and indexed element.
float32 operator () (int32 i) const
{
return (&x)[i];
}
/// Write to an indexed element.
float32& operator () (int32 i)
{
return (&x)[i];
}
/// Add a vector to this vector.
void operator += (const b2Vec2& v)
{
x += v.x; y += v.y;
}
/// Subtract a vector from this vector.
void operator -= (const b2Vec2& v)
{
x -= v.x; y -= v.y;
}
/// Multiply this vector by a scalar.
void operator *= (float32 a)
{
x *= a; y *= a;
}
/// Get the length of this vector (the norm).
float32 Length() const
{
return b2Sqrt(x * x + y * y);
}
/// Get the length squared. For performance, use this instead of
/// b2Vec2::Length (if possible).
float32 LengthSquared() const
{
return x * x + y * y;
}
/// Convert this vector into a unit vector. Returns the length.
float32 Normalize()
{
float32 length = Length();
if (length < b2_epsilon)
{
return 0.0f;
}
float32 invLength = 1.0f / length;
x *= invLength;
y *= invLength;
return length;
}
/// Does this vector contain finite coordinates?
bool IsValid() const
{
return b2IsValid(x) && b2IsValid(y);
}
/// Get the skew vector such that dot(skew_vec, other) == cross(vec, other)
b2Vec2 Skew() const
{
return b2Vec2(-y, x);
}
float32 x, y;
};
/// Add a float to a vector.
inline b2Vec2 operator + (const b2Vec2& v, float f)
{
return b2Vec2(v.x + f, v.y + f);
}
/// Substract a float from a vector.
inline b2Vec2 operator - (const b2Vec2& v, float f)
{
return b2Vec2(v.x - f, v.y - f);
}
/// Multiply a float with a vector.
inline b2Vec2 operator * (const b2Vec2& v, float f)
{
return b2Vec2(v.x * f, v.y * f);
}
/// Divide a vector by a float.
inline b2Vec2 operator / (const b2Vec2& v, float f)
{
return b2Vec2(v.x / f, v.y / f);
}
/// A 3D column vector with 3 elements.
struct b2Vec3
{
/// Default constructor does nothing (for performance).
b2Vec3() {}
/// Construct using coordinates.
b2Vec3(float32 x, float32 y, float32 z) : x(x), y(y), z(z) {}
/// Set this vector to all zeros.
void SetZero() { x = 0.0f; y = 0.0f; z = 0.0f; }
/// Set this vector to some specified coordinates.
void Set(float32 x_, float32 y_, float32 z_) { x = x_; y = y_; z = z_; }
/// Negate this vector.
b2Vec3 operator -() const { b2Vec3 v; v.Set(-x, -y, -z); return v; }
/// Add a vector to this vector.
void operator += (const b2Vec3& v)
{
x += v.x; y += v.y; z += v.z;
}
/// Subtract a vector from this vector.
void operator -= (const b2Vec3& v)
{
x -= v.x; y -= v.y; z -= v.z;
}
/// Multiply this vector by a scalar.
void operator *= (float32 s)
{
x *= s; y *= s; z *= s;
}
/// Get the length of this vector (the norm).
float32 Length() const
{
return b2Sqrt(x * x + y * y + z * z);
}
/// Convert this vector into a unit vector. Returns the length.
float32 Normalize()
{
float32 length = Length();
if (length < b2_epsilon)
{
return 0.0f;
}
float32 invLength = 1.0f / length;
x *= invLength;
y *= invLength;
z *= invLength;
return length;
}
float32 x, y, z;
};
/// A 4D column vector with 4 elements.
struct b2Vec4
{
/// Default constructor does nothing (for performance).
b2Vec4() {}
/// Construct using coordinates.
b2Vec4(float32 x, float32 y, float32 z, float32 w) : x(x), y(y), z(z), w(w) {}
float32 x, y, z, w;
};
/// A 2-by-2 matrix. Stored in column-major order.
struct b2Mat22
{
/// The default constructor does nothing (for performance).
b2Mat22() {}
/// Construct this matrix using columns.
b2Mat22(const b2Vec2& c1, const b2Vec2& c2)
{
ex = c1;
ey = c2;
}
/// Construct this matrix using scalars.
b2Mat22(float32 a11, float32 a12, float32 a21, float32 a22)
{
ex.x = a11; ex.y = a21;
ey.x = a12; ey.y = a22;
}
/// Initialize this matrix using columns.
void Set(const b2Vec2& c1, const b2Vec2& c2)
{
ex = c1;
ey = c2;
}
/// Set this to the identity matrix.
void SetIdentity()
{
ex.x = 1.0f; ey.x = 0.0f;
ex.y = 0.0f; ey.y = 1.0f;
}
/// Set this matrix to all zeros.
void SetZero()
{
ex.x = 0.0f; ey.x = 0.0f;
ex.y = 0.0f; ey.y = 0.0f;
}
b2Mat22 GetInverse() const
{
float32 a = ex.x, b = ey.x, c = ex.y, d = ey.y;
b2Mat22 B;
float32 det = a * d - b * c;
if (det != 0.0f)
{
det = 1.0f / det;
}
B.ex.x = det * d; B.ey.x = -det * b;
B.ex.y = -det * c; B.ey.y = det * a;
return B;
}
/// Solve A * x = b, where b is a column vector. This is more efficient
/// than computing the inverse in one-shot cases.
b2Vec2 Solve(const b2Vec2& b) const
{
float32 a11 = ex.x, a12 = ey.x, a21 = ex.y, a22 = ey.y;
float32 det = a11 * a22 - a12 * a21;
if (det != 0.0f)
{
det = 1.0f / det;
}
b2Vec2 x;
x.x = det * (a22 * b.x - a12 * b.y);
x.y = det * (a11 * b.y - a21 * b.x);
return x;
}
b2Vec2 ex, ey;
};
/// A 3-by-3 matrix. Stored in column-major order.
struct b2Mat33
{
/// The default constructor does nothing (for performance).
b2Mat33() {}
/// Construct this matrix using columns.
b2Mat33(const b2Vec3& c1, const b2Vec3& c2, const b2Vec3& c3)
{
ex = c1;
ey = c2;
ez = c3;
}
/// Set this matrix to all zeros.
void SetZero()
{
ex.SetZero();
ey.SetZero();
ez.SetZero();
}
/// Solve A * x = b, where b is a column vector. This is more efficient
/// than computing the inverse in one-shot cases.
b2Vec3 Solve33(const b2Vec3& b) const;
/// Solve A * x = b, where b is a column vector. This is more efficient
/// than computing the inverse in one-shot cases. Solve only the upper
/// 2-by-2 matrix equation.
b2Vec2 Solve22(const b2Vec2& b) const;
/// Get the inverse of this matrix as a 2-by-2.
/// Returns the zero matrix if singular.
void GetInverse22(b2Mat33* M) const;
/// Get the symmetric inverse of this matrix as a 3-by-3.
/// Returns the zero matrix if singular.
void GetSymInverse33(b2Mat33* M) const;
b2Vec3 ex, ey, ez;
};
/// Rotation
struct b2Rot
{
b2Rot() {}
/// Initialize from an angle in radians
explicit b2Rot(float32 angle)
{
/// TODO_ERIN optimize
s = sinf(angle);
c = cosf(angle);
}
/// Set using an angle in radians.
void Set(float32 angle)
{
/// TODO_ERIN optimize
s = sinf(angle);
c = cosf(angle);
}
/// Set to the identity rotation
void SetIdentity()
{
s = 0.0f;
c = 1.0f;
}
/// Get the angle in radians
float32 GetAngle() const
{
return b2Atan2(s, c);
}
/// Get the x-axis
b2Vec2 GetXAxis() const
{
return b2Vec2(c, s);
}
/// Get the u-axis
b2Vec2 GetYAxis() const
{
return b2Vec2(-s, c);
}
/// Sine and cosine
float32 s, c;
};
/// A transform contains translation and rotation. It is used to represent
/// the position and orientation of rigid frames.
struct b2Transform
{
/// The default constructor does nothing.
b2Transform() {}
/// Initialize using a position vector and a rotation.
b2Transform(const b2Vec2& position, const b2Rot& rotation) : p(position), q(rotation) {}
/// Set this to the identity transform.
void SetIdentity()
{
p.SetZero();
q.SetIdentity();
}
/// Set this based on the position and angle.
void Set(const b2Vec2& position, float32 angle)
{
p = position;
q.Set(angle);
}
#if LIQUIDFUN_EXTERNAL_LANGUAGE_API
/// Get x-coordinate of p.
float32 GetPositionX() const { return p.x; }
/// Get y-coordinate of p.
float32 GetPositionY() const { return p.y; }
/// Get sine-component of q.
float32 GetRotationSin() const { return q.s; }
/// Get cosine-component of q.
float32 GetRotationCos() const { return q.c; }
#endif // LIQUIDFUN_EXTERNAL_LANGUAGE_API
b2Vec2 p;
b2Rot q;
};
/// This describes the motion of a body/shape for TOI computation.
/// Shapes are defined with respect to the body origin, which may
/// no coincide with the center of mass. However, to support dynamics
/// we must interpolate the center of mass position.
struct b2Sweep
{
/// Get the interpolated transform at a specific time.
/// @param beta is a factor in [0,1], where 0 indicates alpha0.
void GetTransform(b2Transform* xfb, float32 beta) const;
/// Advance the sweep forward, yielding a new initial state.
/// @param alpha the new initial time.
void Advance(float32 alpha);
/// Normalize the angles.
void Normalize();
b2Vec2 localCenter; ///< local center of mass position
b2Vec2 c0, c; ///< center world positions
float32 a0, a; ///< world angles
/// Fraction of the current time step in the range [0,1]
/// c0 and a0 are the positions at alpha0.
float32 alpha0;
};
/// Useful constant
extern const b2Vec2 b2Vec2_zero;
/// Perform the dot product on two vectors.
inline float32 b2Dot(const b2Vec2& a, const b2Vec2& b)
{
return a.x * b.x + a.y * b.y;
}
/// Perform the cross product on two vectors. In 2D this produces a scalar.
inline float32 b2Cross(const b2Vec2& a, const b2Vec2& b)
{
return a.x * b.y - a.y * b.x;
}
/// Perform the cross product on a vector and a scalar. In 2D this produces
/// a vector.
inline b2Vec2 b2Cross(const b2Vec2& a, float32 s)
{
return b2Vec2(s * a.y, -s * a.x);
}
/// Perform the cross product on a scalar and a vector. In 2D this produces
/// a vector.
inline b2Vec2 b2Cross(float32 s, const b2Vec2& a)
{
return b2Vec2(-s * a.y, s * a.x);
}
/// Multiply a matrix times a vector. If a rotation matrix is provided,
/// then this transforms the vector from one frame to another.
inline b2Vec2 b2Mul(const b2Mat22& A, const b2Vec2& v)
{
return b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y);
}
/// Multiply a matrix transpose times a vector. If a rotation matrix is provided,
/// then this transforms the vector from one frame to another (inverse transform).
inline b2Vec2 b2MulT(const b2Mat22& A, const b2Vec2& v)
{
return b2Vec2(b2Dot(v, A.ex), b2Dot(v, A.ey));
}
/// Add two vectors component-wise.
inline b2Vec2 operator + (const b2Vec2& a, const b2Vec2& b)
{
return b2Vec2(a.x + b.x, a.y + b.y);
}
/// Subtract two vectors component-wise.
inline b2Vec2 operator - (const b2Vec2& a, const b2Vec2& b)
{
return b2Vec2(a.x - b.x, a.y - b.y);
}
inline b2Vec2 operator * (float32 s, const b2Vec2& a)
{
return b2Vec2(s * a.x, s * a.y);
}
inline bool operator == (const b2Vec2& a, const b2Vec2& b)
{
return a.x == b.x && a.y == b.y;
}
inline bool operator != (const b2Vec2& a, const b2Vec2& b)
{
return !operator==(a, b);
}
inline float32 b2Distance(const b2Vec2& a, const b2Vec2& b)
{
b2Vec2 c = a - b;
return c.Length();
}
inline float32 b2DistanceSquared(const b2Vec2& a, const b2Vec2& b)
{
b2Vec2 c = a - b;
return b2Dot(c, c);
}
inline b2Vec3 operator * (float32 s, const b2Vec3& a)
{
return b2Vec3(s * a.x, s * a.y, s * a.z);
}
/// Add two vectors component-wise.
inline b2Vec3 operator + (const b2Vec3& a, const b2Vec3& b)
{
return b2Vec3(a.x + b.x, a.y + b.y, a.z + b.z);
}
/// Subtract two vectors component-wise.
inline b2Vec3 operator - (const b2Vec3& a, const b2Vec3& b)
{
return b2Vec3(a.x - b.x, a.y - b.y, a.z - b.z);
}
/// Perform the dot product on two vectors.
inline float32 b2Dot(const b2Vec3& a, const b2Vec3& b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
/// Perform the cross product on two vectors.
inline b2Vec3 b2Cross(const b2Vec3& a, const b2Vec3& b)
{
return b2Vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
}
inline b2Mat22 operator + (const b2Mat22& A, const b2Mat22& B)
{
return b2Mat22(A.ex + B.ex, A.ey + B.ey);
}
// A * B
inline b2Mat22 b2Mul(const b2Mat22& A, const b2Mat22& B)
{
return b2Mat22(b2Mul(A, B.ex), b2Mul(A, B.ey));
}
// A^T * B
inline b2Mat22 b2MulT(const b2Mat22& A, const b2Mat22& B)
{
b2Vec2 c1(b2Dot(A.ex, B.ex), b2Dot(A.ey, B.ex));
b2Vec2 c2(b2Dot(A.ex, B.ey), b2Dot(A.ey, B.ey));
return b2Mat22(c1, c2);
}
/// Multiply a matrix times a vector.
inline b2Vec3 b2Mul(const b2Mat33& A, const b2Vec3& v)
{
return v.x * A.ex + v.y * A.ey + v.z * A.ez;
}
/// Multiply a matrix times a vector.
inline b2Vec2 b2Mul22(const b2Mat33& A, const b2Vec2& v)
{
return b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y);
}
/// Multiply two rotations: q * r
inline b2Rot b2Mul(const b2Rot& q, const b2Rot& r)
{
// [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc]
// [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc]
// s = qs * rc + qc * rs
// c = qc * rc - qs * rs
b2Rot qr;
qr.s = q.s * r.c + q.c * r.s;
qr.c = q.c * r.c - q.s * r.s;
return qr;
}
/// Transpose multiply two rotations: qT * r
inline b2Rot b2MulT(const b2Rot& q, const b2Rot& r)
{
// [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc]
// [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc]
// s = qc * rs - qs * rc
// c = qc * rc + qs * rs
b2Rot qr;
qr.s = q.c * r.s - q.s * r.c;
qr.c = q.c * r.c + q.s * r.s;
return qr;
}
/// Rotate a vector
inline b2Vec2 b2Mul(const b2Rot& q, const b2Vec2& v)
{
return b2Vec2(q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y);
}
/// Inverse rotate a vector
inline b2Vec2 b2MulT(const b2Rot& q, const b2Vec2& v)
{
return b2Vec2(q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y);
}
inline b2Vec2 b2Mul(const b2Transform& T, const b2Vec2& v)
{
float32 x = (T.q.c * v.x - T.q.s * v.y) + T.p.x;
float32 y = (T.q.s * v.x + T.q.c * v.y) + T.p.y;
return b2Vec2(x, y);
}
inline b2Vec2 b2MulT(const b2Transform& T, const b2Vec2& v)
{
float32 px = v.x - T.p.x;
float32 py = v.y - T.p.y;
float32 x = (T.q.c * px + T.q.s * py);
float32 y = (-T.q.s * px + T.q.c * py);
return b2Vec2(x, y);
}
// v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p
// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p
inline b2Transform b2Mul(const b2Transform& A, const b2Transform& B)
{
b2Transform C;
C.q = b2Mul(A.q, B.q);
C.p = b2Mul(A.q, B.p) + A.p;
return C;
}
// v2 = A.q' * (B.q * v1 + B.p - A.p)
// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
inline b2Transform b2MulT(const b2Transform& A, const b2Transform& B)
{
b2Transform C;
C.q = b2MulT(A.q, B.q);
C.p = b2MulT(A.q, B.p - A.p);
return C;
}
template <typename T>
inline T b2Abs(T a)
{
return a > T(0) ? a : -a;
}
inline b2Vec2 b2Abs(const b2Vec2& a)
{
return b2Vec2(b2Abs(a.x), b2Abs(a.y));
}
inline b2Mat22 b2Abs(const b2Mat22& A)
{
return b2Mat22(b2Abs(A.ex), b2Abs(A.ey));
}
template <typename T>
inline T b2Min(T a, T b)
{
return a < b ? a : b;
}
inline b2Vec2 b2Min(const b2Vec2& a, const b2Vec2& b)
{
return b2Vec2(b2Min(a.x, b.x), b2Min(a.y, b.y));
}
template <typename T>
inline T b2Max(T a, T b)
{
return a > b ? a : b;
}
inline b2Vec2 b2Max(const b2Vec2& a, const b2Vec2& b)
{
return b2Vec2(b2Max(a.x, b.x), b2Max(a.y, b.y));
}
template <typename T>
inline T b2Clamp(T a, T low, T high)
{
return b2Max(low, b2Min(a, high));
}
inline b2Vec2 b2Clamp(const b2Vec2& a, const b2Vec2& low, const b2Vec2& high)
{
return b2Max(low, b2Min(a, high));
}
template<typename T> inline void b2Swap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
}
/// "Next Largest Power of 2
/// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm
/// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with
/// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next
/// largest power of 2. For a 32-bit value:"
inline uint32 b2NextPowerOfTwo(uint32 x)
{
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return x + 1;
}
inline bool b2IsPowerOfTwo(uint32 x)
{
bool result = x > 0 && (x & (x - 1)) == 0;
return result;
}
inline void b2Sweep::GetTransform(b2Transform* xf, float32 beta) const
{
xf->p = (1.0f - beta) * c0 + beta * c;
float32 angle = (1.0f - beta) * a0 + beta * a;
xf->q.Set(angle);
// Shift to origin
xf->p -= b2Mul(xf->q, localCenter);
}
inline void b2Sweep::Advance(float32 alpha)
{
b2Assert(alpha0 < 1.0f);
float32 beta = (alpha - alpha0) / (1.0f - alpha0);
c0 += beta * (c - c0);
a0 += beta * (a - a0);
alpha0 = alpha;
}
/// Normalize an angle in radians to be between -pi and pi
inline void b2Sweep::Normalize()
{
float32 twoPi = 2.0f * b2_pi;
float32 d = twoPi * floorf(a0 / twoPi);
a0 -= d;
a -= d;
}
#endif
+136
View File
@@ -0,0 +1,136 @@
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
* Copyright (c) 2013 Google, Inc.
*
* 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.
*/
#include <Box2D/Common/b2Settings.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
b2Version b2_version = {2, 3, 0};
#define LIQUIDFUN_VERSION_MAJOR 1
#define LIQUIDFUN_VERSION_MINOR 1
#define LIQUIDFUN_VERSION_REVISION 0
#define LIQUIDFUN_STRING_EXPAND(X) #X
#define LIQUIDFUN_STRING(X) LIQUIDFUN_STRING_EXPAND(X)
static void* b2AllocDefault(int32 size, void* callbackData);
static void b2FreeDefault(void* mem, void* callbackData);
const b2Version b2_liquidFunVersion = {
LIQUIDFUN_VERSION_MAJOR, LIQUIDFUN_VERSION_MINOR,
LIQUIDFUN_VERSION_REVISION,
};
const char *b2_liquidFunVersionString =
"LiquidFun "
LIQUIDFUN_STRING(LIQUIDFUN_VERSION_MAJOR) "."
LIQUIDFUN_STRING(LIQUIDFUN_VERSION_MINOR) "."
LIQUIDFUN_STRING(LIQUIDFUN_VERSION_REVISION);
static int32 b2_numAllocs = 0;
// Initialize default allocator.
static b2AllocFunction b2_allocCallback = b2AllocDefault;
static b2FreeFunction b2_freeCallback = b2FreeDefault;
static void *b2_callbackData = NULL;
// Default implementation of b2AllocFunction.
static void* b2AllocDefault(int32 size, void* callbackData)
{
B2_NOT_USED(callbackData);
return malloc(size);
}
// Default implementation of b2FreeFunction.
static void b2FreeDefault(void* mem, void* callbackData)
{
B2_NOT_USED(callbackData);
free(mem);
}
/// Set alloc and free callbacks to override the default behavior of using
/// malloc() and free() for dynamic memory allocation.
/// Set allocCallback and freeCallback to NULL to restore the default
/// allocator (malloc / free).
void b2SetAllocFreeCallbacks(b2AllocFunction allocCallback,
b2FreeFunction freeCallback, void* callbackData)
{
b2Assert((allocCallback && freeCallback) ||
(!allocCallback && !freeCallback));
b2Assert(0 == b2GetNumAllocs());
if (allocCallback && freeCallback)
{
b2_allocCallback = allocCallback;
b2_freeCallback = freeCallback;
b2_callbackData = callbackData;
}
else
{
b2_allocCallback = b2AllocDefault;
b2_freeCallback = b2FreeDefault;
b2_callbackData = NULL;
}
}
// Memory allocators. Modify these to use your own allocator.
void* b2Alloc(int32 size)
{
b2_numAllocs++;
return b2_allocCallback(size, b2_callbackData);
}
void b2Free(void* mem)
{
b2_numAllocs--;
b2_freeCallback(mem, b2_callbackData);
}
void b2SetNumAllocs(const int32 numAllocs)
{
b2_numAllocs = numAllocs;
}
int32 b2GetNumAllocs()
{
return b2_numAllocs;
}
// You can modify this to use your logging facility.
void b2Log(const char* string, ...)
{
#if DEBUG
va_list args;
va_start(args, string);
vprintf(string, args);
va_end(args);
#else
B2_NOT_USED(string);
#endif
}
class Validator
{
public:
Validator()
{
b2Assert(sizeof(uint64)==8);
b2Assert(sizeof(int64)==8);
}
} validate;
+267
View File
@@ -0,0 +1,267 @@
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
* Copyright (c) 2013 Google, Inc.
*
* 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.
*/
#ifndef B2_SETTINGS_H
#define B2_SETTINGS_H
#include <stddef.h>
#include <assert.h>
#include <float.h>
#define B2_NOT_USED(x) ((void)(x))
#if DEBUG && !defined(NDEBUG)
#define b2Assert(A) assert(A)
#define B2_ASSERT_ENABLED 1
#else
#define b2Assert(A)
#define B2_ASSERT_ENABLED 0
#endif
// Statement which is compiled out when DEBUG isn't defined.
#if DEBUG
#define B2_DEBUG_STATEMENT(A) A
#else
#define B2_DEBUG_STATEMENT(A)
#endif // DEBUG
// Calculate the size of a static array.
#define B2_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
typedef signed char int8;
typedef signed short int16;
typedef signed int int32;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef float float32;
typedef double float64;
#ifdef WIN32
typedef __int64 int64;
typedef unsigned __int64 uint64;
#else // !WIN32
typedef long long int64;
typedef unsigned long long uint64;
#endif
#define b2_maxFloat FLT_MAX
#define b2_epsilon FLT_EPSILON
#define b2_pi 3.14159265359f
#if !defined(b2Inline)
#if defined(__GNUC__)
#define b2Inline __attribute__((always_inline))
#else
#define b2Inline inline
#endif // defined(__GNUC__)
#endif // !defined(b2Inline)
// We expand the API so that other languages (e.g. Java) can call into
// our C++ more easily. Only set if when the flag is not externally defined.
#if !defined(LIQUIDFUN_EXTERNAL_LANGUAGE_API)
#if SWIG || LIQUIDFUN_UNIT_TESTS
#define LIQUIDFUN_EXTERNAL_LANGUAGE_API 1
#else
#define LIQUIDFUN_EXTERNAL_LANGUAGE_API 0
#endif
#endif
/// @file
/// Global tuning constants based on meters-kilograms-seconds (MKS) units.
///
// Collision
/// The maximum number of contact points between two convex shapes. Do
/// not change this value.
#define b2_maxManifoldPoints 2
/// The maximum number of vertices on a convex polygon. You cannot increase
/// this too much because b2BlockAllocator has a maximum object size.
#define b2_maxPolygonVertices 8
/// This is used to fatten AABBs in the dynamic tree. This allows proxies
/// to move by a small amount without triggering a tree adjustment.
/// This is in meters.
#define b2_aabbExtension 0.1f
/// This is used to fatten AABBs in the dynamic tree. This is used to predict
/// the future position based on the current displacement.
/// This is a dimensionless multiplier.
#define b2_aabbMultiplier 2.0f
/// A small length used as a collision and constraint tolerance. Usually it is
/// chosen to be numerically significant, but visually insignificant.
#define b2_linearSlop 0.005f
/// A small angle used as a collision and constraint tolerance. Usually it is
/// chosen to be numerically significant, but visually insignificant.
#define b2_angularSlop (2.0f / 180.0f * b2_pi)
/// The radius of the polygon/edge shape skin. This should not be modified. Making
/// this smaller means polygons will have an insufficient buffer for continuous collision.
/// Making it larger may create artifacts for vertex collision.
#define b2_polygonRadius (2.0f * b2_linearSlop)
/// Maximum number of sub-steps per contact in continuous physics simulation.
#define b2_maxSubSteps 8
// Dynamics
/// Maximum number of contacts to be handled to solve a TOI impact.
#define b2_maxTOIContacts 32
/// A velocity threshold for elastic collisions. Any collision with a relative linear
/// velocity below this threshold will be treated as inelastic.
#define b2_velocityThreshold 1.0f
/// The maximum linear position correction used when solving constraints. This helps to
/// prevent overshoot.
#define b2_maxLinearCorrection 0.2f
/// The maximum angular position correction used when solving constraints. This helps to
/// prevent overshoot.
#define b2_maxAngularCorrection (8.0f / 180.0f * b2_pi)
/// The maximum linear velocity of a body. This limit is very large and is used
/// to prevent numerical problems. You shouldn't need to adjust this.
#define b2_maxTranslation 2.0f
#define b2_maxTranslationSquared (b2_maxTranslation * b2_maxTranslation)
/// The maximum angular velocity of a body. This limit is very large and is used
/// to prevent numerical problems. You shouldn't need to adjust this.
#define b2_maxRotation (0.5f * b2_pi)
#define b2_maxRotationSquared (b2_maxRotation * b2_maxRotation)
/// This scale factor controls how fast overlap is resolved. Ideally this would be 1 so
/// that overlap is removed in one time step. However using values close to 1 often lead
/// to overshoot.
#define b2_baumgarte 0.2f
#define b2_toiBaugarte 0.75f
// Particle
/// NEON SIMD requires 16-bit particle indices
#if !defined(B2_USE_16_BIT_PARTICLE_INDICES) && defined(LIQUIDFUN_SIMD_NEON)
#define B2_USE_16_BIT_PARTICLE_INDICES
#endif
/// A symbolic constant that stands for particle allocation error.
#define b2_invalidParticleIndex (-1)
#ifdef B2_USE_16_BIT_PARTICLE_INDICES
#define b2_maxParticleIndex 0x7FFF
#else
#define b2_maxParticleIndex 0x7FFFFFFF
#endif
/// The default distance between particles, multiplied by the particle diameter.
#define b2_particleStride 0.75f
/// The minimum particle weight that produces pressure.
#define b2_minParticleWeight 1.0f
/// The upper limit for particle pressure.
#define b2_maxParticlePressure 0.25f
/// The upper limit for force between particles.
#define b2_maxParticleForce 0.5f
/// The maximum distance between particles in a triad, multiplied by the
/// particle diameter.
#define b2_maxTriadDistance 2
#define b2_maxTriadDistanceSquared (b2_maxTriadDistance * b2_maxTriadDistance)
/// The initial size of particle data buffers.
#define b2_minParticleSystemBufferCapacity 256
/// The time into the future that collisions against barrier particles will be detected.
#define b2_barrierCollisionTime 2.5f
// Sleep
/// The time that a body must be still before it will go to sleep.
#define b2_timeToSleep 0.5f
/// A body cannot sleep if its linear velocity is above this tolerance.
#define b2_linearSleepTolerance 0.01f
/// A body cannot sleep if its angular velocity is above this tolerance.
#define b2_angularSleepTolerance (2.0f / 180.0f * b2_pi)
// Memory Allocation
/// Implement this function to use your own memory allocator.
void* b2Alloc(int32 size);
/// If you implement b2Alloc, you should also implement this function.
void b2Free(void* mem);
/// Use this function to override b2Alloc() without recompiling this library.
typedef void* (*b2AllocFunction)(int32 size, void* callbackData);
/// Use this function to override b2Free() without recompiling this library.
typedef void (*b2FreeFunction)(void* mem, void* callbackData);
/// Set alloc and free callbacks to override the default behavior of using
/// malloc() and free() for dynamic memory allocation.
/// Set allocCallback and freeCallback to NULL to restore the default
/// allocator (malloc / free).
void b2SetAllocFreeCallbacks(b2AllocFunction allocCallback,
b2FreeFunction freeCallback,
void* callbackData);
/// Set the number of calls to b2Alloc minus the number of calls to b2Free.
/// This can be used to disable the empty heap check in
/// b2SetAllocFreeCallbacks() which can be useful for testing.
void b2SetNumAllocs(const int32 numAllocs);
/// Get number of calls to b2Alloc minus number of calls to b2Free.
int32 b2GetNumAllocs();
/// Logging function.
void b2Log(const char* string, ...);
/// Version numbering scheme.
/// See http://en.wikipedia.org/wiki/Software_versioning
struct b2Version
{
int32 major; ///< significant changes
int32 minor; ///< incremental changes
int32 revision; ///< bug fixes
};
/// Current version.
/// Version of Box2D, LiquidFun is based upon.
extern b2Version b2_version;
/// Global variable is used to identify the version of LiquidFun.
extern const b2Version b2_liquidFunVersion;
/// String which identifies the current version of LiquidFun.
/// b2_liquidFunVersionString is used by Google developers to identify which
/// applications uploaded to Google Play are using this library. This allows
/// the development team at Google to determine the popularity of the library.
/// How it works: Applications that are uploaded to the Google Play Store are
/// scanned for this version string. We track which applications are using it
/// to measure popularity. You are free to remove it (of course) but we would
/// appreciate if you left it in.
extern const char *b2_liquidFunVersionString;
#endif
+244
View File
@@ -0,0 +1,244 @@
/*
* Copyright (c) 2014 Google, Inc.
*
* 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.
*/
#ifndef B2_SLAB_ALLOCATOR_H
#define B2_SLAB_ALLOCATOR_H
#include <stddef.h>
#include <stdint.h>
#include <new>
#include <Box2D/Common/b2IntrusiveList.h>
#include <Box2D/Common/b2FreeList.h>
#include <Box2D/Common/b2Settings.h>
#include <Box2D/Common/b2TrackedBlock.h>
/// Freelist based allocator for fixed sized items from slabs (memory
/// preallocated from the heap).
/// T should be a class which has a default constructor and implements the
/// member function "b2IntrusiveList* GetListNode()".
/// All objects in a slab are constructed when a slab is created and destructed
/// when a slab is freed.
template<typename T>
class b2SlabAllocator
{
private:
// Information about a slab.
class Slab
{
public:
/// Initialize a slab with the number of items it contains.
Slab(uint32 numberOfItems) :
m_numberOfItems(numberOfItems)
{
B2_NOT_USED(m_padding);
// This assumes that this class is packed on at least a 4-byte
// boundary with no padding. Verify the assumption.
b2Assert(sizeof(*this) == b2_mallocAlignment);
}
/// Empty destructor.
~Slab() { }
/// Get the number of items in this slab.
uint32 GetNumberOfItems() const { return m_numberOfItems; }
/// Get a pointer to the first item in the slab.
T* GetFirstItem() const
{
return (T*)((uint8*)(this + 1));
}
/// Get a pointer to the end of the slab.
/// NOTE: This is a pointer after the last byte of the slab not the
/// last item in the slab.
T* GetItemEnd() const { return GetFirstItem() + GetNumberOfItems(); }
private:
/// Number of items in the slab.
uint32 m_numberOfItems;
/// Padding to align the first item in the slab to b2_mallocAlignment.
uint8 m_padding[b2_mallocAlignment - sizeof(uint32)];
};
public:
/// Initialize the allocator to allocate itemsPerSlab of type T for each
/// slab that is allocated.
b2SlabAllocator(const uint32 itemsPerSlab) :
m_itemsPerSlab(itemsPerSlab)
{
}
/// Free all allocated slabs.
~b2SlabAllocator()
{
FreeAllSlabs();
}
/// Set size of the next allocated slab using the number of items per
/// slab. Setting this value to zero disables further slab allocation.
void SetItemsPerSlab(uint32 itemsPerSlab)
{
m_itemsPerSlab = itemsPerSlab;
}
// Get the size of the next allocated slab.
uint32 GetItemsPerSlab() const
{
return m_itemsPerSlab;
}
/// Allocate a item from the slab.
T* Allocate()
{
// Allocate a slab if needed here.
if (m_freeList.GetFreeList()->GetFreeList().IsEmpty() &&
!AllocateSlab())
return NULL;
return m_freeList.Allocate();
}
/// Free an item from the slab.
void Free(T *object)
{
m_freeList.Free(object);
}
/// Allocate a slab, construct instances of T and add them to the free
/// pool.
bool AllocateSlab()
{
if (!m_itemsPerSlab) return false;
const uint32 slabSize = sizeof(Slab) + (sizeof(T) * m_itemsPerSlab);
void* const memory = m_slabs.Allocate(slabSize);
if (!memory) return false;
Slab* const slab = new (BlockGetSlab(memory)) Slab(m_itemsPerSlab);
T* item = slab->GetFirstItem();
for (uint32 i = 0; i < m_itemsPerSlab; ++i, ++item)
{
m_freeList.AddToFreeList(new (item) T);
}
return true;
}
/// Free all slabs.
void FreeAllSlabs()
{
const b2TypedIntrusiveListNode<b2TrackedBlock>& slabList =
m_slabs.GetList();
while (!slabList.IsEmpty())
{
FreeSlab(BlockGetSlab(slabList.GetNext()->GetMemory()));
}
}
/// Free all empty slabs.
/// This method is slow - O(M^N) - since this class doesn't track
/// the association between each item and slab.
void FreeEmptySlabs()
{
const b2IntrusiveListNode& freeItemList =
m_freeList.GetFreeList()->GetFreeList();
const b2IntrusiveListNode* freeItemListTerminator =
freeItemList.GetTerminator();
const b2TypedIntrusiveListNode<b2TrackedBlock>& slabList =
m_slabs.GetList();
const b2TypedIntrusiveListNode<b2TrackedBlock>* slabListTerminator =
slabList.GetTerminator();
b2TrackedBlock* block = slabList.GetNext();
while (block != slabListTerminator)
{
// Get the Slab from the memory associated with the block.
Slab* const slab = BlockGetSlab(block->GetMemory());
block = block->GetNext();
// Determine the range of memory the Slab owns.
const uint8* const slabItemStart = (uint8*)slab->GetFirstItem();
const uint8* const slabItemEnd = (uint8*)slab->GetItemEnd();
// Count all free items that are owned by the current slab.
uint8 freeItems = 0;
bool empty = false;
for (b2IntrusiveListNode* itemNode = freeItemList.GetNext();
itemNode != freeItemListTerminator;
itemNode = itemNode->GetNext())
{
const uint8* itemNodeAddress = (uint8*)itemNode;
if (itemNodeAddress >= slabItemStart &&
itemNodeAddress <= slabItemEnd)
{
++freeItems;
if (slab->GetNumberOfItems() == freeItems)
{
empty = true;
break;
}
}
}
// If a slab is empty, free it.
if (empty)
{
FreeSlab(slab);
}
}
}
/// Get the item allocator freelist.
const b2TypedFreeList<T>& GetFreeList() const
{
return m_freeList;
}
private:
/// Destroy all objects in a slab and free the slab.
void FreeSlab(Slab * const slab)
{
b2Assert(slab);
const uint32 numberOfItems = slab->GetNumberOfItems();
T* item = slab->GetFirstItem();
for (uint32 i = 0; i < numberOfItems; ++i, ++item)
{
item->~T();
}
slab->~Slab();
m_slabs.Free(slab);
}
/// Get a pointer to a Slab from a block of memory in m_slabs.
Slab* BlockGetSlab(void *memory)
{
return (Slab*)memory;
}
/// Get a pointer to the first item in the array of items referenced by a
/// Slab.
T* SlabGetFirstItem(Slab* slab)
{
return (T*)(slab + 1);
}
private:
/// Contains a list of b2TrackedBlock instances where each b2TrackedBlock's
/// associated user memory contains a Slab followed by instances of T.
b2TrackedBlockAllocator m_slabs;
/// Number of items to allocate in the next allocated slab.
uint32 m_itemsPerSlab;
/// Freelist which contains instances of T.
b2TypedFreeList<T> m_freeList;
};
#endif // B2_SLAB_ALLOCATOR_H
+120
View File
@@ -0,0 +1,120 @@
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
*
* 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.
*/
#include <Box2D/Common/b2StackAllocator.h>
#include <Box2D/Common/b2Math.h>
#include <string.h>
b2StackAllocator::b2StackAllocator()
{
m_index = 0;
m_allocation = 0;
m_maxAllocation = 0;
m_entryCount = 0;
}
b2StackAllocator::~b2StackAllocator()
{
b2Assert(m_index == 0);
b2Assert(m_entryCount == 0);
}
void* b2StackAllocator::Allocate(int32 size)
{
b2Assert(m_entryCount < b2_maxStackEntries);
const int32 roundedSize = (size + ALIGN_MASK) & ~ALIGN_MASK;
b2StackEntry* entry = m_entries + m_entryCount;
entry->size = roundedSize;
if (m_index + roundedSize > b2_stackSize)
{
entry->data = (char*)b2Alloc(roundedSize);
entry->usedMalloc = true;
}
else
{
entry->data = m_data + m_index;
entry->usedMalloc = false;
m_index += roundedSize;
}
m_allocation += roundedSize;
m_maxAllocation = b2Max(m_maxAllocation, m_allocation);
++m_entryCount;
return entry->data;
}
void* b2StackAllocator::Reallocate(void* p, int32 size)
{
b2Assert(m_entryCount > 0);
b2StackEntry* entry = m_entries + m_entryCount - 1;
b2Assert(p == entry->data);
B2_NOT_USED(p);
int32 incrementSize = size - entry->size;
if (incrementSize > 0)
{
if (entry->usedMalloc)
{
void* data = b2Alloc(size);
memcpy(data, entry->data, entry->size);
b2Free(entry->data);
entry->data = (char*)data;
}
else if (m_index + incrementSize > b2_stackSize)
{
void* data = b2Alloc(size);
memcpy(data, entry->data, entry->size);
m_index -= entry->size;
entry->data = (char*)data;
entry->usedMalloc = true;
}
else
{
m_index += incrementSize;
m_allocation += incrementSize;
m_maxAllocation = b2Max(m_maxAllocation, m_allocation);
}
entry->size = size;
}
return entry->data;
}
void b2StackAllocator::Free(void* p)
{
b2Assert(m_entryCount > 0);
b2StackEntry* entry = m_entries + m_entryCount - 1;
b2Assert(p == entry->data);
if (entry->usedMalloc)
{
b2Free(p);
}
else
{
m_index -= entry->size;
}
m_allocation -= entry->size;
--m_entryCount;
p = NULL;
}
int32 b2StackAllocator::GetMaxAllocation() const
{
return m_maxAllocation;
}
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
*
* 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.
*/
#ifndef B2_STACK_ALLOCATOR_H
#define B2_STACK_ALLOCATOR_H
#include <Box2D/Common/b2Settings.h>
const int32 b2_stackSize = 100 * 1024; // 100k
const int32 b2_maxStackEntries = 32;
struct b2StackEntry
{
char* data;
int32 size;
bool usedMalloc;
};
// This is a stack allocator used for fast per step allocations.
// You must nest allocate/free pairs. The code will assert
// if you try to interleave multiple allocate/free pairs.
class b2StackAllocator
{
public:
enum { MIN_ALIGNMENT = sizeof(void*) }; // Must be a power of 2
enum { ALIGN_MASK = MIN_ALIGNMENT - 1 };
b2StackAllocator();
~b2StackAllocator();
void* Allocate(int32 size);
void* Reallocate(void* p, int32 size);
void Free(void* p);
int32 GetMaxAllocation() const;
private:
char m_data[b2_stackSize];
int32 m_index;
int32 m_allocation;
int32 m_maxAllocation;
b2StackEntry m_entries[b2_maxStackEntries];
int32 m_entryCount;
};
#endif
+67
View File
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2013 Google, Inc.
*
* 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.
*/
#include "b2Stat.h"
#include <algorithm>
#include <cfloat>
b2Stat::b2Stat()
{
Clear();
}
void b2Stat::Record( float32 t )
{
m_total += t;
m_min = std::min(m_min,t);
m_max = std::max(m_max,t);
m_count++;
}
int b2Stat::GetCount() const
{
return m_count;
}
float32 b2Stat::GetMean() const
{
if (m_count == 0)
{
return 0.0f;
}
return (float32)(m_total / m_count);
}
float32 b2Stat::GetMin() const
{
return m_min;
}
float32 b2Stat::GetMax() const
{
return m_max;
}
void b2Stat::Clear()
{
m_count = 0;
m_total = 0;
m_min = FLT_MAX;
m_max = -FLT_MAX;
}
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2013 Google, Inc.
*
* 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.
*/
#ifndef B2_STAT
#define B2_STAT
#include <Box2D/Common/b2Settings.h>
/// Calculates min/max/mean of a set of samples
class b2Stat
{
public:
b2Stat();
/// Record a sample
void Record( float32 t );
/// Returns the number of recorded samples
int GetCount() const;
/// Returns the mean of all recorded samples,
/// Returns 0 if there are no recorded samples
float32 GetMean() const;
/// Returns the min of all recorded samples,
/// FLT_MAX if there are no recorded samples
float32 GetMin() const;
/// Returns the max of all recorded samples,
/// -FLT_MAX if there are no recorded samples
float32 GetMax() const;
/// Erase all recorded samples
void Clear();
private:
int m_count;
float64 m_total;
float32 m_min;
float32 m_max;
};
#endif
+134
View File
@@ -0,0 +1,134 @@
/*
* Copyright (c) 2011 Erin Catto http://box2d.org
* Copyright (c) 2014 Google, Inc.
*
* 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.
*/
#include <Box2D/Common/b2Timer.h>
#if defined(_WIN32)
float64 b2Timer::s_invFrequency = 0.0f;
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef BOOL (WINAPI *SystemGetTimeFunc)(_Out_ LARGE_INTEGER *lpFrequency);
SystemGetTimeFunc systemGetTimeFunc = ::QueryPerformanceCounter;
SystemGetTimeFunc systemGetFreqFunc = ::QueryPerformanceFrequency;
int64 b2Timer::GetTicks()
{
LARGE_INTEGER largeInteger;
systemGetTimeFunc(&largeInteger);
return largeInteger.QuadPart;
}
b2Timer::b2Timer()
{
LARGE_INTEGER largeInteger;
if (s_invFrequency == 0.0f)
{
systemGetFreqFunc(&largeInteger);
s_invFrequency = float64(largeInteger.QuadPart);
if (s_invFrequency > 0.0f)
{
s_invFrequency = 1000.0f / s_invFrequency;
}
}
m_start = GetTicks();
}
void b2Timer::Reset()
{
m_start = GetTicks();
}
float32 b2Timer::GetMilliseconds() const
{
int64 elapsed = GetTicks() - m_start;
return (float32)(s_invFrequency * elapsed);
}
#elif defined(__linux__) || defined (__APPLE__)
#include <sys/time.h>
#include <time.h>
// systemGetTimeFunc is defined with external linkage to allow unit
// test to mock out the system time function
#if defined(__linux__)
typedef int (*SystemGetTimeFunc)(clockid_t clk_id, struct timespec *tp);
SystemGetTimeFunc systemGetTimeFunc = ::clock_gettime;
#elif defined(__APPLE__)
typedef int (*SystemGetTimeFunc)(struct timeval * tp, void * tzp);
SystemGetTimeFunc systemGetTimeFunc = ::gettimeofday;
#endif
int64 b2Timer::GetTicks()
{
static const int NSEC_PER_SEC = 1000000000;
#ifdef __linux__
timespec ts;
systemGetTimeFunc(CLOCK_MONOTONIC,&ts);
return ((int64)ts.tv_sec) * NSEC_PER_SEC + ts.tv_nsec;
#else
timeval t;
systemGetTimeFunc(&t, 0);
return ((int64)t.tv_sec) * NSEC_PER_SEC + t.tv_usec * 1000;
#endif
}
b2Timer::b2Timer()
{
Reset();
}
void b2Timer::Reset()
{
m_start = GetTicks();
}
float32 b2Timer::GetMilliseconds() const
{
static const float32 kTicksToMs = 0.000001f;
return kTicksToMs * (float32)(GetTicks() - m_start);
}
#else
b2Timer::b2Timer()
{
}
void b2Timer::Reset()
{
}
float32 b2Timer::GetMilliseconds() const
{
return 0.0f;
}
#endif
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2011 Erin Catto http://box2d.org
* Copyright (c) 2014 Google, Inc.
*
* 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.
*/
#ifndef B2_TIMER_H
#define B2_TIMER_H
#include <Box2D/Common/b2Settings.h>
/// Timer for profiling. This has platform specific code and may
/// not work on every platform.
class b2Timer
{
public:
/// Constructor
b2Timer();
/// Reset the timer.
void Reset();
/// Get the time since construction or the last reset.
float32 GetMilliseconds() const;
private:
/// Get platform specific tick count
static int64 GetTicks();
#if defined(_WIN32)
static float64 s_invFrequency;
#endif
int64 m_start;
};
#endif
+111
View File
@@ -0,0 +1,111 @@
/*
* Copyright (c) 2014 Google, Inc.
*
* 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.
*/
#include <Box2D/Common/b2TrackedBlock.h>
#include <stddef.h>
#include <stdint.h>
#include <new>
// Initialize this block with a reference to "this".
b2TrackedBlock::b2TrackedBlock()
{
b2TrackedBlock** pointerToThis =
(b2TrackedBlock**)((uint8*)GetMemory() - sizeof(b2TrackedBlock**));
*pointerToThis = this;
}
/// Get the allocated memory associated with this block.
void* b2TrackedBlock::GetMemory() const
{
// The size of data in this without padding.
static const uint32 kSizeOfThisWithNoPadding =
sizeof(*this) - sizeof(m_padding) + sizeof(b2TrackedBlock**);
// Make sure b2_mallocAlignment is base2.
b2Assert(((b2_mallocAlignment - 1) & b2_mallocAlignment) == 0);
// Round the pointer following data in this to b2_mallocAlignment.
uint8* const aligned = (uint8*)(
((uintptr_t)this + kSizeOfThisWithNoPadding + b2_mallocAlignment - 1) &
~((uintptr_t)b2_mallocAlignment - 1));
// Verify offset doesn't overlap data in this.
b2Assert((uintptr_t)aligned - (uintptr_t)this >= kSizeOfThisWithNoPadding);
return aligned;
}
/// Allocate a b2TrackedBlock returning a pointer to memory of size
/// bytes that can be used by the caller.
void* b2TrackedBlock::Allocate(uint32 size)
{
void* memory = (b2TrackedBlock*)b2Alloc(sizeof(b2TrackedBlock) +
size);
if (!memory)
{
return NULL;
}
return (new(memory) b2TrackedBlock)->GetMemory();
}
/// Get a b2TrackedBlock from a pointer to memory returned by
/// b2TrackedBlock::Allocate().
b2TrackedBlock* b2TrackedBlock::GetFromMemory(void *memory)
{
uint8* const aligned = (uint8*)memory;
b2Assert(memory);
b2TrackedBlock **blockPtr = (b2TrackedBlock**)(aligned -
sizeof(b2TrackedBlock**));
b2Assert(*blockPtr);
return *blockPtr;
}
/// Free a block of memory returned by b2TrackedBlock::Allocate()
void b2TrackedBlock::Free(void *memory)
{
Free(GetFromMemory(memory));
}
/// Free a b2TrackedBlock.
void b2TrackedBlock::Free(b2TrackedBlock *block)
{
b2Assert(block);
block->~b2TrackedBlock();
b2Free(block);
}
/// Allocate a block of size bytes using b2TrackedBlock::Allocate().
void* b2TrackedBlockAllocator::Allocate(uint32 size)
{
void *memory = b2TrackedBlock::Allocate(size);
m_blocks.InsertBefore(b2TrackedBlock::GetFromMemory(memory));
return memory;
}
/// Free a block returned by Allocate().
void b2TrackedBlockAllocator::Free(void *memory)
{
b2TrackedBlock::Free(memory);
}
/// Free all allocated blocks.
void b2TrackedBlockAllocator::FreeAll()
{
while (!m_blocks.IsEmpty())
{
b2TrackedBlock::Free(m_blocks.GetNext());
}
}
+92
View File
@@ -0,0 +1,92 @@
/*
* Copyright (c) 2014 Google, Inc.
*
* 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.
*/
#ifndef B2_TRACKED_BLOCK_H
#define B2_TRACKED_BLOCK_H
#include <Box2D/Common/b2IntrusiveList.h>
#include <Box2D/Common/b2Settings.h>
/// Alignment (in bytes) of user memory associated with b2TrackedBlock.
const int32 b2_mallocAlignment = 32;
/// Allocated block of memory that can be tracked in a b2IntrusiveList.
class b2TrackedBlock : public b2TypedIntrusiveListNode<b2TrackedBlock>
{
private:
// Initialize this block with a reference to "this".
b2TrackedBlock();
// Remove the block from the list.
~b2TrackedBlock() { }
public:
/// Get the allocated memory associated with this block.
void* GetMemory() const;
private:
// Padding required to align the pointer to user memory in the block
// to b2_mallocAlignment.
uint8 m_padding[b2_mallocAlignment + sizeof(b2TrackedBlock**)];
public:
/// Allocate a b2TrackedBlock returning a pointer to memory of size
/// bytes that can be used by the caller.
static void* Allocate(uint32 size);
/// Get a b2TrackedBlock from a pointer to memory returned by
/// b2TrackedBlock::Allocate().
static b2TrackedBlock* GetFromMemory(void *memory);
/// Free a block of memory returned by b2TrackedBlock::Allocate()
static void Free(void *memory);
/// Free a b2TrackedBlock.
static void Free(b2TrackedBlock *block);
};
/// Allocator of blocks which are tracked in a list.
class b2TrackedBlockAllocator
{
public:
/// Initialize.
b2TrackedBlockAllocator() {}
/// Free all allocated blocks.
~b2TrackedBlockAllocator()
{
FreeAll();
}
/// Allocate a block of size bytes using b2TrackedBlock::Allocate().
void* Allocate(uint32 size);
/// Free a block returned by Allocate().
void Free(void *memory);
/// Free all allocated blocks.
void FreeAll();
// Get the list of allocated blocks.
const b2TypedIntrusiveListNode<b2TrackedBlock>& GetList() const
{
return m_blocks;
}
private:
b2TypedIntrusiveListNode<b2TrackedBlock> m_blocks;
};
#endif // B2_TRACKED_BLOCK_H