#pragma once
#include "arena_allocator.h"
#include "bitset.h"
#include "block_allocator.h"
#include "broad_phase.h"
#include "constraint_graph.h"
#include "id_pool.h"
#include "box3d/types.h"
#define B3_DEBUG_POINT_CAPACITY 64
#define B3_DEBUG_LINE_CAPACITY 64
typedef struct b3Body b3Body;
typedef struct b3Recording b3Recording;
typedef struct b3Contact b3Contact;
typedef struct b3Island b3Island;
typedef struct b3Joint b3Joint;
typedef struct b3Sensor b3Sensor;
typedef struct b3SensorTaskContext b3SensorTaskContext;
typedef struct b3SensorHit b3SensorHit;
typedef struct b3Shape b3Shape;
typedef struct b3SolverSet b3SolverSet;
b3DeclareArray( b3BlockAllocator );
b3DeclareArray( b3Body );
b3DeclareArray( b3SolverSet );
b3DeclareArray( b3Joint );
b3DeclareArray( b3Contact );
b3DeclareArray( b3Island );
b3DeclareArray( b3Shape );
b3DeclareArray( b3Sensor );
b3DeclareArray( b3SensorTaskContext );
b3DeclareArray( b3SensorHit );
b3DeclareArray( b3BodyMoveEvent );
b3DeclareArray( b3SensorBeginTouchEvent );
b3DeclareArray( b3ContactBeginTouchEvent );
b3DeclareArray( b3SensorEndTouchEvent );
b3DeclareArray( b3ContactEndTouchEvent );
b3DeclareArray( b3ContactHitEvent );
b3DeclareArray( b3JointEvent );
enum b3SetType
{
b3_staticSet = 0,
b3_disabledSet = 1,
b3_awakeSet = 2,
b3_firstSleepingSet = 3,
};
typedef struct b3DebugPoint
{
b3Pos p;
int label;
float value;
b3HexColor color;
} b3DebugPoint;
typedef struct b3DebugLine
{
b3Pos p1, p2;
int label;
b3HexColor color;
} b3DebugLine;
typedef struct b3TaskContext
{
b3Arena arena;
b3Array( b3SensorHit ) sensorHits;
b3BitSet contactStateBitSet;
b3BitSet jointStateBitSet;
b3BitSet hitEventBitSet;
bool hasHitEvents;
b3BitSet enlargedSimBitSet;
b3BitSet awakeIslandBitSet;
float splitSleepTime;
int splitIslandId;
int satCallCount;
int satCacheHitCount;
int distanceIterations;
int pushBackIterations;
int rootIterations;
int recycledContactCount;
b3DebugPoint points[B3_DEBUG_POINT_CAPACITY];
int pointCount;
b3DebugLine lines[B3_DEBUG_LINE_CAPACITY];
int lineCount;
int manifoldCounts[B3_CONTACT_MANIFOLD_COUNT_BUCKETS];
char cacheLine[64];
} b3TaskContext;
b3DeclareArray( b3TaskContext );
typedef struct b3World
{
b3Stack stack;
b3BroadPhase broadPhase;
b3ConstraintGraph constraintGraph;
b3Array( b3BlockAllocator ) manifoldAllocators;
b3Mutex* manifoldAllocatorMutex;
b3IdPool bodyIdPool;
b3Array( b3Body ) bodies;
b3IdPool solverSetIdPool;
b3Array( b3SolverSet ) solverSets;
b3IdPool jointIdPool;
b3Array( b3Joint ) joints;
b3IdPool contactIdPool;
b3Array( b3Contact ) contacts;
b3IdPool islandIdPool;
b3Array( b3Island ) islands;
b3IdPool shapeIdPool;
b3Array( b3Shape ) shapes;
void* hullDatabase;
b3Array( b3Sensor ) sensors;
b3Array( b3TaskContext ) taskContexts;
b3Array( b3SensorTaskContext ) sensorTaskContexts;
b3Array( b3BodyMoveEvent ) bodyMoveEvents;
b3Array( b3SensorBeginTouchEvent ) sensorBeginEvents;
b3Array( b3ContactBeginTouchEvent ) contactBeginEvents;
b3Array( b3SensorEndTouchEvent ) sensorEndEvents[2];
b3Array( b3ContactEndTouchEvent ) contactEndEvents[2];
int endEventArrayIndex;
b3Array( b3ContactHitEvent ) contactHitEvents;
b3Array( b3JointEvent ) jointEvents;
b3BitSet debugBodySet;
b3BitSet debugJointSet;
b3BitSet debugContactSet;
b3BitSet debugIslandSet;
b3CreateDebugShapeCallback* createDebugShape;
b3DestroyDebugShapeCallback* destroyDebugShape;
void* userDebugShapeContext;
uint64_t stepIndex;
int splitIslandId;
b3Vec3 gravity;
float hitEventThreshold;
float restitutionThreshold;
float maxLinearSpeed;
float contactSpeed;
float contactHertz;
float contactDampingRatio;
float contactRecycleDistance;
b3FrictionCallback* frictionCallback;
b3RestitutionCallback* restitutionCallback;
uint16_t generation;
b3Profile profile;
int satCallCount;
int satCacheHitCount;
int manifoldCounts[B3_CONTACT_MANIFOLD_COUNT_BUCKETS];
b3Capacity maxCapacity;
b3PreSolveFcn* preSolveFcn;
void* preSolveContext;
b3CustomFilterFcn* customFilterFcn;
void* customFilterContext;
int workerCount;
b3EnqueueTaskCallback* enqueueTaskFcn;
b3FinishTaskCallback* finishTaskFcn;
void* userTaskContext;
void* userTreeTask;
struct b3Scheduler* scheduler;
void* userData;
float inv_h;
float inv_dt;
int activeTaskCount;
int taskCount;
uint16_t worldId;
bool enableSleep;
bool locked;
struct b3Recording* recording;
bool enableWarmStarting;
bool enableContinuous;
bool enableSpeculative;
bool inUse;
} b3World;
b3World* b3GetUnlockedWorldFromId( b3WorldId id );
b3World* b3GetWorldFromId( b3WorldId id );
b3World* b3GetUnlockedWorld( int index );
b3World* b3GetWorld( int index );
void b3ValidateConnectivity( b3World* world );
void b3ValidateSolverSets( b3World* world );
void b3ValidateContacts( b3World* world );
const b3HullData* b3AddHullToDatabase( b3World* world, const b3HullData* src );
const b3HullData* b3AddOwnedHullToDatabase( b3World* world, b3HullData* owned );
void b3RemoveHullFromDatabase( b3World* world, const b3HullData* data );
static inline b3Manifold* b3AllocateManifolds( b3World* world, int count )
{
if ( count == 0 )
{
return NULL;
}
int index = count - 1;
b3LockMutex( world->manifoldAllocatorMutex );
int currentCount = world->manifoldAllocators.count;
for ( int i = currentCount; i < count; ++i )
{
b3BlockAllocator allocator = b3CreateBlockAllocator( ( i + 1 ) * sizeof( b3Manifold ), 2 * B3_BLOCK_SIZE );
b3Array_Push( world->manifoldAllocators, allocator );
}
b3BlockAllocator* allocator = b3Array_Get( world->manifoldAllocators, index );
b3Manifold* manifolds = (b3Manifold*)b3AllocateElement( allocator );
b3UnlockMutex( world->manifoldAllocatorMutex );
memset( manifolds, 0, count * sizeof( b3Manifold ) );
return manifolds;
}
static inline void b3FreeManifolds( b3World* world, b3Manifold* manifolds, int count )
{
if ( count == 0 )
{
return;
}
int index = count - 1;
b3LockMutex( world->manifoldAllocatorMutex );
b3BlockAllocator* allocator = b3Array_Get( world->manifoldAllocators, index );
b3FreeElement( allocator, manifolds );
b3UnlockMutex( world->manifoldAllocatorMutex );
}