namespace pp layer
This commit is contained in:
parent
ebbc1a640b
commit
029c88e74e
636
src/pp/pp.c
636
src/pp/pp.c
File diff suppressed because it is too large
Load Diff
228
src/pp/pp.h
228
src/pp/pp.h
@ -2,103 +2,103 @@
|
||||
//~ Binds
|
||||
|
||||
//- Bind kinds
|
||||
Enum(BindKind)
|
||||
Enum(PP_BindKind)
|
||||
{
|
||||
BindKind_None,
|
||||
PP_BindKind_None,
|
||||
|
||||
BindKind_MoveUp,
|
||||
BindKind_MoveDown,
|
||||
BindKind_MoveLeft,
|
||||
BindKind_MoveRight,
|
||||
BindKind_Walk,
|
||||
BindKind_Fire,
|
||||
BindKind_AltFire,
|
||||
PP_BindKind_MoveUp,
|
||||
PP_BindKind_MoveDown,
|
||||
PP_BindKind_MoveLeft,
|
||||
PP_BindKind_MoveRight,
|
||||
PP_BindKind_Walk,
|
||||
PP_BindKind_Fire,
|
||||
PP_BindKind_AltFire,
|
||||
|
||||
BindKind_TestTile,
|
||||
BindKind_DebugClear,
|
||||
BindKind_DebugSpawn1,
|
||||
BindKind_DebugSpawn2,
|
||||
BindKind_DebugSpawn3,
|
||||
BindKind_DebugSpawn4,
|
||||
BindKind_DebugWalls,
|
||||
BindKind_DebugFollow,
|
||||
BindKind_DebugDraw,
|
||||
BindKind_DebugConsole,
|
||||
BindKind_DebugCamera,
|
||||
BindKind_DebugPause,
|
||||
BindKind_DebugStep,
|
||||
BindKind_DebugDrag,
|
||||
BindKind_DebugDelete,
|
||||
BindKind_DebugTeleport,
|
||||
BindKind_DebugExplode,
|
||||
BindKind_DebugToggleTopmost,
|
||||
BindKind_FullscreenMod,
|
||||
BindKind_Fullscreen,
|
||||
BindKind_ZoomIn,
|
||||
BindKind_ZoomOut,
|
||||
BindKind_Pan,
|
||||
PP_BindKind_TestTile,
|
||||
PP_BindKind_DebugClear,
|
||||
PP_BindKind_DebugSpawn1,
|
||||
PP_BindKind_DebugSpawn2,
|
||||
PP_BindKind_DebugSpawn3,
|
||||
PP_BindKind_DebugSpawn4,
|
||||
PP_BindKind_DebugWalls,
|
||||
PP_BindKind_DebugFollow,
|
||||
PP_BindKind_DebugDraw,
|
||||
PP_BindKind_DebugConsole,
|
||||
PP_BindKind_DebugCamera,
|
||||
PP_BindKind_DebugPause,
|
||||
PP_BindKind_DebugStep,
|
||||
PP_BindKind_DebugDrag,
|
||||
PP_BindKind_DebugDelete,
|
||||
PP_BindKind_DebugTeleport,
|
||||
PP_BindKind_DebugExplode,
|
||||
PP_BindKind_DebugToggleTopmost,
|
||||
PP_BindKind_FullscreenMod,
|
||||
PP_BindKind_Fullscreen,
|
||||
PP_BindKind_ZoomIn,
|
||||
PP_BindKind_ZoomOut,
|
||||
PP_BindKind_Pan,
|
||||
|
||||
#if RtcIsEnabled
|
||||
/* Debug */
|
||||
|
||||
BindKind_ResetDebugSteps,
|
||||
BindKind_IncrementDebugSteps,
|
||||
BindKind_DecrementDebugSteps,
|
||||
PP_BindKind_ResetDebugSteps,
|
||||
PP_BindKind_IncrementDebugSteps,
|
||||
PP_BindKind_DecrementDebugSteps,
|
||||
#endif
|
||||
|
||||
BindKind_Count
|
||||
PP_BindKind_Count
|
||||
};
|
||||
|
||||
//- Test bindings
|
||||
|
||||
/* TODO: Remove this */
|
||||
Global Readonly BindKind g_binds[Btn_Count] = {
|
||||
[Btn_W] = BindKind_MoveUp,
|
||||
[Btn_S] = BindKind_MoveDown,
|
||||
[Btn_A] = BindKind_MoveLeft,
|
||||
[Btn_D] = BindKind_MoveRight,
|
||||
[Btn_M1] = BindKind_Fire,
|
||||
[Btn_M2] = BindKind_AltFire,
|
||||
Global Readonly PP_BindKind g_binds[Btn_Count] = {
|
||||
[Btn_W] = PP_BindKind_MoveUp,
|
||||
[Btn_S] = PP_BindKind_MoveDown,
|
||||
[Btn_A] = PP_BindKind_MoveLeft,
|
||||
[Btn_D] = PP_BindKind_MoveRight,
|
||||
[Btn_M1] = PP_BindKind_Fire,
|
||||
[Btn_M2] = PP_BindKind_AltFire,
|
||||
#if 0
|
||||
[Btn_Alt] = BindKind_Walk,
|
||||
[Btn_Alt] = PP_BindKind_Walk,
|
||||
#endif
|
||||
|
||||
/* Testing */
|
||||
[Btn_Z] = BindKind_TestTile,
|
||||
[Btn_M5] = BindKind_DebugDrag,
|
||||
[Btn_M4] = BindKind_DebugDelete,
|
||||
[Btn_F] = BindKind_DebugExplode,
|
||||
[Btn_T] = BindKind_DebugTeleport,
|
||||
[Btn_C] = BindKind_DebugClear,
|
||||
[Btn_1] = BindKind_DebugSpawn1,
|
||||
[Btn_2] = BindKind_DebugSpawn2,
|
||||
[Btn_3] = BindKind_DebugSpawn3,
|
||||
[Btn_4] = BindKind_DebugSpawn4,
|
||||
[Btn_G] = BindKind_DebugWalls,
|
||||
[Btn_N] = BindKind_DebugStep,
|
||||
[Btn_Q] = BindKind_DebugFollow,
|
||||
[Btn_F1] = BindKind_DebugPause,
|
||||
[Btn_F2] = BindKind_DebugCamera,
|
||||
[Btn_F3] = BindKind_DebugDraw,
|
||||
[Btn_F4] = BindKind_DebugToggleTopmost,
|
||||
[Btn_GraveAccent] = BindKind_DebugConsole,
|
||||
[Btn_Alt] = BindKind_FullscreenMod,
|
||||
[Btn_Enter] = BindKind_Fullscreen,
|
||||
[Btn_MWheelUp] = BindKind_ZoomIn,
|
||||
[Btn_MWheelDown] = BindKind_ZoomOut,
|
||||
[Btn_M3] = BindKind_Pan,
|
||||
[Btn_Z] = PP_BindKind_TestTile,
|
||||
[Btn_M5] = PP_BindKind_DebugDrag,
|
||||
[Btn_M4] = PP_BindKind_DebugDelete,
|
||||
[Btn_F] = PP_BindKind_DebugExplode,
|
||||
[Btn_T] = PP_BindKind_DebugTeleport,
|
||||
[Btn_C] = PP_BindKind_DebugClear,
|
||||
[Btn_1] = PP_BindKind_DebugSpawn1,
|
||||
[Btn_2] = PP_BindKind_DebugSpawn2,
|
||||
[Btn_3] = PP_BindKind_DebugSpawn3,
|
||||
[Btn_4] = PP_BindKind_DebugSpawn4,
|
||||
[Btn_G] = PP_BindKind_DebugWalls,
|
||||
[Btn_N] = PP_BindKind_DebugStep,
|
||||
[Btn_Q] = PP_BindKind_DebugFollow,
|
||||
[Btn_F1] = PP_BindKind_DebugPause,
|
||||
[Btn_F2] = PP_BindKind_DebugCamera,
|
||||
[Btn_F3] = PP_BindKind_DebugDraw,
|
||||
[Btn_F4] = PP_BindKind_DebugToggleTopmost,
|
||||
[Btn_GraveAccent] = PP_BindKind_DebugConsole,
|
||||
[Btn_Alt] = PP_BindKind_FullscreenMod,
|
||||
[Btn_Enter] = PP_BindKind_Fullscreen,
|
||||
[Btn_MWheelUp] = PP_BindKind_ZoomIn,
|
||||
[Btn_MWheelDown] = PP_BindKind_ZoomOut,
|
||||
[Btn_M3] = PP_BindKind_Pan,
|
||||
|
||||
#if RtcIsEnabled
|
||||
[Btn_ForwardSlash] = BindKind_ResetDebugSteps,
|
||||
[Btn_Comma] = BindKind_DecrementDebugSteps,
|
||||
[Btn_Period] = BindKind_IncrementDebugSteps
|
||||
[Btn_ForwardSlash] = PP_BindKind_ResetDebugSteps,
|
||||
[Btn_Comma] = PP_BindKind_DecrementDebugSteps,
|
||||
[Btn_Period] = PP_BindKind_IncrementDebugSteps
|
||||
#endif
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Stats
|
||||
|
||||
Struct(SecondsStat)
|
||||
Struct(PP_SecondsStat)
|
||||
{
|
||||
u64 last_second_start;
|
||||
u64 last_second_end;
|
||||
@ -108,39 +108,39 @@ Struct(SecondsStat)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Console log
|
||||
|
||||
Struct(ConsoleLog)
|
||||
Struct(PP_ConsoleLog)
|
||||
{
|
||||
String msg;
|
||||
i32 level;
|
||||
i32 color_index;
|
||||
P_DateTime datetime;
|
||||
i64 time_ns;
|
||||
ConsoleLog *prev;
|
||||
ConsoleLog *next;
|
||||
PP_ConsoleLog *prev;
|
||||
PP_ConsoleLog *next;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Sim decode queue
|
||||
|
||||
Struct(DecodeQueueNode)
|
||||
Struct(PP_DecodeQueueNode)
|
||||
{
|
||||
Client *client;
|
||||
PP_Client *client;
|
||||
u64 tick;
|
||||
u64 base_tick;
|
||||
String tmp_encoded;
|
||||
DecodeQueueNode *next;
|
||||
PP_DecodeQueueNode *next;
|
||||
};
|
||||
|
||||
Struct(DecodeQueue)
|
||||
Struct(PP_DecodeQueue)
|
||||
{
|
||||
DecodeQueueNode *first;
|
||||
DecodeQueueNode *last;
|
||||
PP_DecodeQueueNode *first;
|
||||
PP_DecodeQueueNode *last;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ State types
|
||||
|
||||
Struct(BindState)
|
||||
Struct(PP_BindState)
|
||||
{
|
||||
b32 is_held; /* Is this bind held down this frame */
|
||||
u32 num_presses; /* How many times was this bind's pressed since last frame */
|
||||
@ -149,7 +149,7 @@ Struct(BindState)
|
||||
u32 num_releases; /* How many times was this bind released since last frame */
|
||||
};
|
||||
|
||||
Struct(SharedUserState)
|
||||
Struct(PP_SharedUserState)
|
||||
{
|
||||
Atomic32 shutdown;
|
||||
|
||||
@ -159,18 +159,18 @@ Struct(SharedUserState)
|
||||
Arena *arena;
|
||||
String connect_address_str;
|
||||
|
||||
ClientStore *user_client_store;
|
||||
Client *user_unblended_client; /* Contains snapshots received from local sim */
|
||||
Client *user_blended_client; /* Contains single snapshot from result of blending local sim snapshots */
|
||||
Snapshot *ss_blended; /* Points to blended snapshot contained in blended client */
|
||||
PP_ClientStore *user_client_store;
|
||||
PP_Client *user_unblended_client; /* Contains snapshots received from local sim */
|
||||
PP_Client *user_blended_client; /* Contains single snapshot from result of blending local sim snapshots */
|
||||
PP_Snapshot *ss_blended; /* Points to blended snapshot contained in blended client */
|
||||
|
||||
u64 user_tick;
|
||||
u64 window_os_gen;
|
||||
|
||||
//- Usage stats
|
||||
i64 last_second_reset_ns;
|
||||
SecondsStat net_bytes_read;
|
||||
SecondsStat net_bytes_sent;
|
||||
PP_SecondsStat net_bytes_read;
|
||||
PP_SecondsStat net_bytes_sent;
|
||||
|
||||
//- Renderer gbuffers
|
||||
GPU_Resource *albedo;
|
||||
@ -195,13 +195,13 @@ Struct(SharedUserState)
|
||||
i64 gpu_submit_fence_target;
|
||||
|
||||
//- Bind state
|
||||
BindState bind_states[BindKind_Count];
|
||||
PP_BindState bind_states[PP_BindKind_Count];
|
||||
|
||||
//- Debug console
|
||||
Mutex console_logs_mutex;
|
||||
Arena *console_logs_arena;
|
||||
ConsoleLog *first_console_log;
|
||||
ConsoleLog *last_console_log;
|
||||
PP_ConsoleLog *first_console_log;
|
||||
PP_ConsoleLog *last_console_log;
|
||||
i32 console_log_color_indices[P_LogLevel_Count];
|
||||
|
||||
//- Window -> user
|
||||
@ -210,8 +210,8 @@ Struct(SharedUserState)
|
||||
|
||||
//- User -> sim
|
||||
Mutex user_sim_cmd_mutex;
|
||||
ControlData user_sim_cmd_control;
|
||||
EntityId user_hovered_ent;
|
||||
PP_ControlData user_sim_cmd_control;
|
||||
PP_EntKey user_hovered_ent;
|
||||
u64 last_user_sim_cmd_gen;
|
||||
u64 user_sim_cmd_gen;
|
||||
|
||||
@ -220,8 +220,8 @@ Struct(SharedUserState)
|
||||
|
||||
//- Sim -> user
|
||||
Mutex local_to_user_client_mutex;
|
||||
ClientStore *local_to_user_client_store;
|
||||
Client *local_to_user_client;
|
||||
PP_ClientStore *local_to_user_client_store;
|
||||
PP_Client *local_to_user_client;
|
||||
i64 local_to_user_client_publish_dt_ns;
|
||||
i64 local_to_user_client_publish_time_ns;
|
||||
|
||||
@ -251,7 +251,7 @@ Struct(SharedUserState)
|
||||
|
||||
//- Debug camera
|
||||
|
||||
EntityId debug_following;
|
||||
PP_EntKey debug_following;
|
||||
b32 debug_camera;
|
||||
b32 debug_camera_panning;
|
||||
Vec2 debug_camera_pan_start;
|
||||
@ -282,66 +282,66 @@ Struct(SharedUserState)
|
||||
//- Persist end
|
||||
//////////////////////////////
|
||||
|
||||
} extern shared_user_state;
|
||||
} extern PP_shared_user_state;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Swap types
|
||||
|
||||
Struct(SwappedUserState)
|
||||
Struct(PP_SwappedUserState)
|
||||
{
|
||||
SharedUserState s;
|
||||
PP_SharedUserState s;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Startup
|
||||
|
||||
void StartupUser(void);
|
||||
void PP_StartupUser(void);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Shutdown
|
||||
|
||||
ExitFuncDef(ShutdownUser);
|
||||
ExitFuncDef(PP_ShutdownUser);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Ui helpers
|
||||
|
||||
void PushGameUiStyle(void);
|
||||
void DrawDebugXform(Xform xf, u32 color_x, u32 color_y);
|
||||
void DrawDebugMovement(Entity *ent);
|
||||
String DebugStringFromEntity(Arena *arena, Entity *ent);
|
||||
void PP_PushGameUiStyle(void);
|
||||
void PP_DrawDebugXform(Xform xf, u32 color_x, u32 color_y);
|
||||
void PP_DrawDebugMovement(PP_Ent *ent);
|
||||
String PP_DebugStringFromEnt(Arena *arena, PP_Ent *ent);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Console draw operations
|
||||
|
||||
P_LogEventCallbackFuncDef(ConsoleLogCallback, log);
|
||||
void DrawDebugConsole(b32 minimized);
|
||||
P_LogEventCallbackFuncDef(PP_ConsoleLogCallback, log);
|
||||
void PP_DrawDebugConsole(b32 minimized);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Gpu buffer helpers
|
||||
|
||||
GPU_Resource *AcquireGbuffer(GPU_Format format, Vec2I32 size);
|
||||
GPU_Resource *PP_AcquireGbuffer(GPU_Format format, Vec2I32 size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Entity sorting
|
||||
//~ Ent sorting
|
||||
|
||||
MergesortCompareFuncDef(EntitySortCmp, arg_a, arg_b, _);
|
||||
MergesortCompareFuncDef(PP_EntSortCmp, arg_a, arg_b, _);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ User update
|
||||
|
||||
void UpdateUser(void);
|
||||
void PP_UpdateUser(void);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ User update job
|
||||
|
||||
JobDecl(UpdateUserOrSleep, EmptySig);
|
||||
JobDecl(PP_UpdateUserOrSleep, EmptySig);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ User input cmds
|
||||
|
||||
void GenerateuserInputCmds(Client *user_input_client, u64 tick);
|
||||
void PP_GenerateuserInputCmds(PP_Client *user_input_client, u64 tick);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Sim update job
|
||||
|
||||
JobDecl(UpdateSim, EmptySig);
|
||||
JobDecl(PP_UpdateSim, EmptySig);
|
||||
|
||||
@ -33,14 +33,14 @@
|
||||
@IncludeGpu pp_draw.gpu
|
||||
|
||||
//- Embeds
|
||||
@EmbedDir GameResources pp_res
|
||||
@EmbedDir PP_Resources pp_res
|
||||
|
||||
//- Shaders
|
||||
@VertexShader MaterialVS
|
||||
@PixelShader MaterialPS
|
||||
@ComputeShader FloodCS
|
||||
@ComputeShader ShadeCS
|
||||
@VertexShader PP_MaterialVS
|
||||
@PixelShader PP_MaterialPS
|
||||
@ComputeShader PP_FloodCS
|
||||
@ComputeShader PP_ShadeCS
|
||||
|
||||
//- Startup
|
||||
@Startup StartupSim
|
||||
@Startup StartupUser
|
||||
@Startup PP_StartupSim
|
||||
@Startup PP_StartupUser
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
ConstantBuffer<MaterialSig> mat_sig : register (b0);
|
||||
ConstantBuffer<FloodSig> flood_sig : register (b0);
|
||||
ConstantBuffer<ShadeSig> shade_sig : register (b0);
|
||||
ConstantBuffer<PP_MaterialSig> PP_mat_sig : register (b0);
|
||||
ConstantBuffer<PP_FloodSig> PP_flood_sig : register (b0);
|
||||
ConstantBuffer<PP_ShadeSig> PP_shade_sig : register (b0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Material
|
||||
|
||||
Struct(MaterialPS_Input)
|
||||
Struct(PP_MaterialPS_Input)
|
||||
{
|
||||
Semantic(Vec4, sv_position);
|
||||
Semantic(nointerpolation Texture2DRid, tex);
|
||||
@ -15,7 +15,7 @@ Struct(MaterialPS_Input)
|
||||
Semantic(Vec4, emittance_lin);
|
||||
};
|
||||
|
||||
Struct(MaterialPS_Output)
|
||||
Struct(PP_MaterialPS_Output)
|
||||
{
|
||||
Semantic(Vec4, sv_target0); /* Albedo */
|
||||
Semantic(Vec4, sv_target1); /* Emittance */
|
||||
@ -23,17 +23,17 @@ Struct(MaterialPS_Output)
|
||||
|
||||
//- Vertex shader
|
||||
|
||||
MaterialPS_Input VSDef(MaterialVS, Semantic(u32, sv_instanceid), Semantic(u32, sv_vertexid))
|
||||
PP_MaterialPS_Input VSDef(PP_MaterialVS, Semantic(u32, sv_instanceid), Semantic(u32, sv_vertexid))
|
||||
{
|
||||
ConstantBuffer<MaterialSig> sig = mat_sig;
|
||||
StructuredBuffer<MaterialInstance> instances = UniformResourceFromRid(sig.instances);
|
||||
MaterialInstance instance = instances[sv_instanceid];
|
||||
ConstantBuffer<PP_MaterialSig> sig = PP_mat_sig;
|
||||
StructuredBuffer<PP_MaterialInstance> instances = UniformResourceFromRid(sig.instances);
|
||||
PP_MaterialInstance instance = instances[sv_instanceid];
|
||||
|
||||
Vec2 mat_uv = RectUvFromVertexId(sv_vertexid);
|
||||
Vec2 mat_uv_centered = mat_uv - 0.5f;
|
||||
Vec2 world_pos = mul(instance.xf, Vec3(mat_uv_centered, 1)).xy;
|
||||
|
||||
MaterialPS_Input result;
|
||||
PP_MaterialPS_Input result;
|
||||
result.sv_position = mul(sig.projection, Vec4(world_pos, 0, 1));
|
||||
result.tex = instance.tex;
|
||||
result.grid_id = instance.grid_id;
|
||||
@ -45,11 +45,11 @@ MaterialPS_Input VSDef(MaterialVS, Semantic(u32, sv_instanceid), Semantic(u32, s
|
||||
|
||||
//- Pixel shader
|
||||
|
||||
MaterialPS_Output PSDef(MaterialPS, MaterialPS_Input input)
|
||||
PP_MaterialPS_Output PSDef(PP_MaterialPS, PP_MaterialPS_Input input)
|
||||
{
|
||||
ConstantBuffer<MaterialSig> sig = mat_sig;
|
||||
ConstantBuffer<PP_MaterialSig> sig = PP_mat_sig;
|
||||
|
||||
MaterialPS_Output result;
|
||||
PP_MaterialPS_Output result;
|
||||
Vec4 albedo = input.tint_lin;
|
||||
|
||||
/* Texture */
|
||||
@ -63,9 +63,9 @@ MaterialPS_Output PSDef(MaterialPS, MaterialPS_Input input)
|
||||
/* Grid */
|
||||
if (input.grid_id < 0xFFFFFFFF)
|
||||
{
|
||||
// StructuredBuffer<MaterialGrid> grids = UniformResourceFromRid(sig.grids);
|
||||
StructuredBuffer<MaterialGrid> grids = ResourceDescriptorHeap[sig.grids];
|
||||
MaterialGrid grid = grids[input.grid_id];
|
||||
// StructuredBuffer<PP_MaterialGrid> grids = UniformResourceFromRid(sig.grids);
|
||||
StructuredBuffer<PP_MaterialGrid> grids = ResourceDescriptorHeap[sig.grids];
|
||||
PP_MaterialGrid grid = grids[input.grid_id];
|
||||
Vec2 grid_pos = input.sv_position.xy + grid.offset;
|
||||
f32 half_thickness = grid.line_thickness / 2;
|
||||
f32 spacing = grid.line_spacing;
|
||||
@ -119,9 +119,9 @@ MaterialPS_Output PSDef(MaterialPS, MaterialPS_Input input)
|
||||
//- Compute shader
|
||||
|
||||
[numthreads(8, 8, 1)]
|
||||
void CSDef(FloodCS, Semantic(Vec3U32, sv_dispatchthreadid))
|
||||
void CSDef(PP_FloodCS, Semantic(Vec3U32, sv_dispatchthreadid))
|
||||
{
|
||||
ConstantBuffer<FloodSig> sig = flood_sig;
|
||||
ConstantBuffer<PP_FloodSig> sig = PP_flood_sig;
|
||||
|
||||
Vec2U32 id = sv_dispatchthreadid.xy;
|
||||
Vec2U32 tex_size = Vec2U32(sig.tex_width, sig.tex_height);
|
||||
@ -181,15 +181,15 @@ void CSDef(FloodCS, Semantic(Vec3U32, sv_dispatchthreadid))
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Shade
|
||||
|
||||
#define LightSamples 16
|
||||
#define LightMarches 16
|
||||
#define LightEdgeFalloff 100
|
||||
#define PP_LightSamples 16
|
||||
#define PP_LightMarches 16
|
||||
#define PP_LightEdgeFalloff 100
|
||||
|
||||
//- Lighting
|
||||
|
||||
f32 RandAngleFromPos(Vec2U32 pos, u32 ray_index)
|
||||
f32 PP_RandAngleFromPos(Vec2U32 pos, u32 ray_index)
|
||||
{
|
||||
ConstantBuffer<ShadeSig> sig = shade_sig;
|
||||
ConstantBuffer<PP_ShadeSig> sig = PP_shade_sig;
|
||||
|
||||
Texture3D<u32> noise_tex = UniformResourceFromRid(sig.noise);
|
||||
Vec3I32 noise_coord = Vec3U32(1, 1, 1);
|
||||
@ -201,16 +201,16 @@ f32 RandAngleFromPos(Vec2U32 pos, u32 ray_index)
|
||||
return ((f32)noise / (f32)0xFFFF) * Tau;
|
||||
}
|
||||
|
||||
Vec3 LightFromDir(Vec2U32 ray_start, Vec2 ray_dir)
|
||||
Vec3 PP_LightFromDir(Vec2U32 ray_start, Vec2 ray_dir)
|
||||
{
|
||||
ConstantBuffer<ShadeSig> sig = shade_sig;
|
||||
ConstantBuffer<PP_ShadeSig> sig = PP_shade_sig;
|
||||
Texture2D<Vec2U32> flood_tex = UniformResourceFromRid(sig.emittance_flood);
|
||||
Texture2D<Vec4> emittance_tex = UniformResourceFromRid(sig.emittance);
|
||||
|
||||
Vec3 result = Vec3(0, 0, 0);
|
||||
Vec2 at_f32 = ray_start;
|
||||
Vec2U32 at_u32 = ray_start;
|
||||
for (u32 i = 0; i < LightMarches; ++i)
|
||||
for (u32 i = 0; i < PP_LightMarches; ++i)
|
||||
{
|
||||
Vec2U32 flood = flood_tex[at_u32];
|
||||
Vec2 dist_vec = at_f32 - (Vec2)flood;
|
||||
@ -220,7 +220,7 @@ Vec3 LightFromDir(Vec2U32 ray_start, Vec2 ray_dir)
|
||||
/* Scale light by distance from edge so that offscreen-lights fade in/out rather than popping in */
|
||||
f32 dist_x = min(abs(sig.tex_width - at_f32.x), at_f32.x);
|
||||
f32 dist_y = min(abs(sig.tex_height - at_f32.y), at_f32.y);
|
||||
f32 dist_scale = min(min(dist_x, dist_y) / LightEdgeFalloff, 1);
|
||||
f32 dist_scale = min(min(dist_x, dist_y) / PP_LightEdgeFalloff, 1);
|
||||
result = emittance_tex[flood].rgb * dist_scale;
|
||||
break;
|
||||
}
|
||||
@ -238,17 +238,17 @@ Vec3 LightFromDir(Vec2U32 ray_start, Vec2 ray_dir)
|
||||
return result;
|
||||
}
|
||||
|
||||
Vec3 AccumulatedLightFromPos(Vec2U32 pos)
|
||||
Vec3 PP_AccumulatedLightFromPos(Vec2U32 pos)
|
||||
{
|
||||
Vec3 result = 0;
|
||||
for (u32 i = 0; i < LightSamples; ++i)
|
||||
for (u32 i = 0; i < PP_LightSamples; ++i)
|
||||
{
|
||||
f32 angle = RandAngleFromPos(pos, i);
|
||||
f32 angle = PP_RandAngleFromPos(pos, i);
|
||||
Vec2 dir = Vec2(cos(angle), sin(angle));
|
||||
Vec3 light_in_dir = LightFromDir(pos, dir);
|
||||
Vec3 light_in_dir = PP_LightFromDir(pos, dir);
|
||||
result += light_in_dir;
|
||||
}
|
||||
result /= LightSamples;
|
||||
result /= PP_LightSamples;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -256,7 +256,7 @@ Vec3 AccumulatedLightFromPos(Vec2U32 pos)
|
||||
|
||||
/* ACES approximation by Krzysztof Narkowicz
|
||||
* https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ */
|
||||
Vec3 ToneMap(Vec3 v)
|
||||
Vec3 PP_ToneMap(Vec3 v)
|
||||
{
|
||||
return saturate((v * (2.51f * v + 0.03f)) / (v * (2.43f * v + 0.59f) + 0.14f));
|
||||
}
|
||||
@ -264,9 +264,9 @@ Vec3 ToneMap(Vec3 v)
|
||||
//- Compute shader
|
||||
|
||||
[numthreads(8, 8, 1)]
|
||||
void CSDef(ShadeCS, Semantic(Vec3U32, sv_dispatchthreadid))
|
||||
void CSDef(PP_ShadeCS, Semantic(Vec3U32, sv_dispatchthreadid))
|
||||
{
|
||||
ConstantBuffer<ShadeSig> sig = shade_sig;
|
||||
ConstantBuffer<PP_ShadeSig> sig = PP_shade_sig;
|
||||
Vec2U32 id = sv_dispatchthreadid.xy;
|
||||
if (id.x < sig.tex_width && id.y < sig.tex_height)
|
||||
{
|
||||
@ -279,17 +279,17 @@ void CSDef(ShadeCS, Semantic(Vec3U32, sv_dispatchthreadid))
|
||||
color *= albedo_tex[id];
|
||||
|
||||
/* Apply lighting */
|
||||
if (!(sig.flags & ShadeFlag_DisableEffects))
|
||||
if (!(sig.flags & PP_ShadeFlag_DisableEffects))
|
||||
{
|
||||
color.rgb *= AccumulatedLightFromPos(id);
|
||||
color.rgb *= PP_AccumulatedLightFromPos(id);
|
||||
}
|
||||
|
||||
/* Apply tone mapping */
|
||||
if (sig.flags & ShadeFlag_ToneMap)
|
||||
if (sig.flags & PP_ShadeFlag_ToneMap)
|
||||
{
|
||||
/* TODO: Dynamic exposure based on average scene luminance */
|
||||
color.rgb *= sig.exposure;
|
||||
color.rgb = ToneMap(color.rgb);
|
||||
color.rgb = PP_ToneMap(color.rgb);
|
||||
}
|
||||
|
||||
/* Apply temporal accumulation */
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Material types
|
||||
|
||||
Struct(MaterialSig)
|
||||
Struct(PP_MaterialSig)
|
||||
{
|
||||
/* ----------------------------------------------------- */
|
||||
Mat4x4 projection; /* 16 consts */
|
||||
@ -12,9 +12,9 @@ Struct(MaterialSig)
|
||||
u32 _pad0; /* 01 consts (padding) */
|
||||
/* ----------------------------------------------------- */
|
||||
};
|
||||
AssertRootConst(MaterialSig, 20);
|
||||
AssertRootConst(PP_MaterialSig, 20);
|
||||
|
||||
Struct(MaterialInstance)
|
||||
Struct(PP_MaterialInstance)
|
||||
{
|
||||
Texture2DRid tex;
|
||||
u32 grid_id;
|
||||
@ -25,15 +25,15 @@ Struct(MaterialInstance)
|
||||
u32 is_light;
|
||||
Vec3 light_emittance_srgb;
|
||||
};
|
||||
#define DefaultMaterialInstance (MaterialInstance) { \
|
||||
.tex = { U32Max }, \
|
||||
.grid_id = U32Max, \
|
||||
.xf = XformIdentity, \
|
||||
.tex_uv1 = VEC2(1, 1), \
|
||||
.tint_srgb = Color_White, \
|
||||
#define PP_DefaultMaterialInstance (PP_MaterialInstance) { \
|
||||
.tex = { U32Max }, \
|
||||
.grid_id = U32Max, \
|
||||
.xf = XformIdentity, \
|
||||
.tex_uv1 = VEC2(1, 1), \
|
||||
.tint_srgb = Color_White, \
|
||||
}
|
||||
|
||||
Struct(MaterialGrid)
|
||||
Struct(PP_MaterialGrid)
|
||||
{
|
||||
f32 line_thickness;
|
||||
f32 line_spacing;
|
||||
@ -44,17 +44,17 @@ Struct(MaterialGrid)
|
||||
u32 x_srgb;
|
||||
u32 y_srgb;
|
||||
};
|
||||
#define DefaultMaterialGrid (MaterialGrid) { \
|
||||
.line_thickness = 1, \
|
||||
.line_spacing = 1, \
|
||||
.bg0_srgb = Color_Black, \
|
||||
.bg0_srgb = Color_White \
|
||||
#define PP_DefaultMaterialGrid (PP_MaterialGrid) { \
|
||||
.line_thickness = 1, \
|
||||
.line_spacing = 1, \
|
||||
.bg0_srgb = Color_Black, \
|
||||
.bg0_srgb = Color_White \
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Flood types
|
||||
|
||||
Struct(FloodSig)
|
||||
Struct(PP_FloodSig)
|
||||
{
|
||||
/* ----------------------------------------------------- */
|
||||
i32 step_len; /* 01 consts */
|
||||
@ -68,16 +68,16 @@ Struct(FloodSig)
|
||||
u32 _pad1; /* 01 consts (padding) */
|
||||
/* ----------------------------------------------------- */
|
||||
};
|
||||
AssertRootConst(FloodSig, 8);
|
||||
AssertRootConst(PP_FloodSig, 8);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Shade types
|
||||
|
||||
#define ShadeFlag_None (0 << 0)
|
||||
#define ShadeFlag_DisableEffects (1 << 0)
|
||||
#define ShadeFlag_ToneMap (1 << 1)
|
||||
#define PP_ShadeFlag_None (0 << 0)
|
||||
#define PP_ShadeFlag_DisableEffects (1 << 0)
|
||||
#define PP_ShadeFlag_ToneMap (1 << 1)
|
||||
|
||||
Struct(ShadeSig)
|
||||
Struct(PP_ShadeSig)
|
||||
{
|
||||
/* ----------------------------------------------------- */
|
||||
Vec4U32 frame_seed; /* 04 consts */
|
||||
@ -102,4 +102,4 @@ Struct(ShadeSig)
|
||||
u32 noise_tex_depth; /* 01 consts */
|
||||
/* ----------------------------------------------------- */
|
||||
};
|
||||
AssertRootConst(ShadeSig, 20);
|
||||
AssertRootConst(PP_ShadeSig, 20);
|
||||
|
||||
378
src/pp/pp_ent.c
378
src/pp/pp_ent.c
@ -1,12 +1,12 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Acquire
|
||||
|
||||
Entity *AcquireRaw(Snapshot *ss, Entity *parent, EntityId id)
|
||||
PP_Ent *PP_AcquireRawEnt(PP_Snapshot *ss, PP_Ent *parent, PP_EntKey id)
|
||||
{
|
||||
Assert(parent->valid);
|
||||
Assert(ss->valid);
|
||||
Assert(ss == parent->ss);
|
||||
Entity *ent;
|
||||
PP_Ent *ent;
|
||||
if (ss->first_free_ent > 0 && ss->first_free_ent < ss->num_ents_reserved)
|
||||
{
|
||||
/* Reuse from free list */
|
||||
@ -16,64 +16,64 @@ Entity *AcquireRaw(Snapshot *ss, Entity *parent, EntityId id)
|
||||
else
|
||||
{
|
||||
/* Make new */
|
||||
ent = PushStructNoZero(ss->ents_arena, Entity);
|
||||
ent = PushStructNoZero(ss->ents_arena, PP_Ent);
|
||||
++ss->num_ents_reserved;
|
||||
}
|
||||
*ent = *NilEntity();
|
||||
*ent = *PP_NilEnt();
|
||||
ent->ss = ss;
|
||||
ent->valid = 1;
|
||||
ent->owner = ss->client->player_id;
|
||||
ent->_is_xform_dirty = 1;
|
||||
++ss->num_ents_allocated;
|
||||
|
||||
SetEntityId(ent, id);
|
||||
Link(ent, parent);
|
||||
PP_SetEntKey(ent, id);
|
||||
PP_Link(ent, parent);
|
||||
|
||||
return ent;
|
||||
}
|
||||
|
||||
/* Acquires a new entity that will not sync */
|
||||
Entity *AcquireLocal(Entity *parent)
|
||||
PP_Ent *PP_AcquireLocalEnt(PP_Ent *parent)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
Entity *e = AcquireRaw(ss, parent, RandomId());
|
||||
PP_Snapshot *ss = parent->ss;
|
||||
PP_Ent *e = PP_AcquireRawEnt(ss, parent, PP_RandomKey());
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity *AcquireLocalWithId(Entity *parent, EntityId id)
|
||||
PP_Ent *PP_AcquireLocalEntWithKey(PP_Ent *parent, PP_EntKey id)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
Entity *e = AcquireRaw(ss, parent, id);
|
||||
PP_Snapshot *ss = parent->ss;
|
||||
PP_Ent *e = PP_AcquireRawEnt(ss, parent, id);
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
}
|
||||
|
||||
/* Acquires a new entity to be synced to clients */
|
||||
Entity *AcquireSyncSrc(Entity *parent)
|
||||
PP_Ent *PP_AcquireSyncSrcEnt(PP_Ent *parent)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
Entity *e = AcquireRaw(ss, parent, RandomId());
|
||||
EnableProp(e, Prop_SyncSrc);
|
||||
PP_Snapshot *ss = parent->ss;
|
||||
PP_Ent *e = PP_AcquireRawEnt(ss, parent, PP_RandomKey());
|
||||
PP_EnableProp(e, PP_Prop_SyncSrc);
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity *AcquireSyncSrcWithId(Entity *parent, EntityId id)
|
||||
PP_Ent *PP_AcquireSyncSrcEntWithKey(PP_Ent *parent, PP_EntKey id)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
Entity *e = AcquireRaw(ss, parent, id);
|
||||
EnableProp(e, Prop_SyncSrc);
|
||||
PP_Snapshot *ss = parent->ss;
|
||||
PP_Ent *e = PP_AcquireRawEnt(ss, parent, id);
|
||||
PP_EnableProp(e, PP_Prop_SyncSrc);
|
||||
e->owner = ss->local_player;
|
||||
return e;
|
||||
}
|
||||
|
||||
/* Acquires a new entity that will sync with incoming net src ents containing id, and coming from the specified owner */
|
||||
Entity *AcquireSyncDst(Entity *parent, EntityId ent_id, EntityId owner_id)
|
||||
PP_Ent *PP_AcquireSyncDstEnt(PP_Ent *parent, PP_EntKey ent_id, PP_EntKey owner_id)
|
||||
{
|
||||
Snapshot *ss = parent->ss;
|
||||
Entity *e = AcquireRaw(ss, parent, ent_id);
|
||||
EnableProp(e, Prop_SyncDst);
|
||||
PP_Snapshot *ss = parent->ss;
|
||||
PP_Ent *e = PP_AcquireRawEnt(ss, parent, ent_id);
|
||||
PP_EnableProp(e, PP_Prop_SyncDst);
|
||||
e->owner = owner_id;
|
||||
return e;
|
||||
}
|
||||
@ -81,51 +81,51 @@ Entity *AcquireSyncDst(Entity *parent, EntityId ent_id, EntityId owner_id)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Release
|
||||
|
||||
void ReleaseRaw(Entity *ent)
|
||||
void PP_ReleaseRawEnt(PP_Ent *ent)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
PP_Snapshot *ss = ent->ss;
|
||||
/* Release children */
|
||||
Entity *child = EntityFromId(ss, ent->first);
|
||||
PP_Ent *child = PP_EntFromKey(ss, ent->first);
|
||||
while (child->valid)
|
||||
{
|
||||
Entity *next = EntityFromId(ss, child->next);
|
||||
ReleaseRaw(child);
|
||||
PP_Ent *next = PP_EntFromKey(ss, child->next);
|
||||
PP_ReleaseRawEnt(child);
|
||||
child = next;
|
||||
}
|
||||
|
||||
/* Release uid */
|
||||
SetEntityId(ent, NilEntityId);
|
||||
PP_SetEntKey(ent, PP_NilEntKey);
|
||||
|
||||
/* Release */
|
||||
ent->valid = 0;
|
||||
ent->next_free = ss->first_free_ent;
|
||||
ss->first_free_ent = IndexFromEntity(ss, ent);
|
||||
ss->first_free_ent = PP_IndexFromEnt(ss, ent);
|
||||
--ss->num_ents_allocated;
|
||||
}
|
||||
|
||||
void Release(Entity *ent)
|
||||
void PP_Release(PP_Ent *ent)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
Entity *parent = EntityFromId(ss, ent->parent);
|
||||
PP_Snapshot *ss = ent->ss;
|
||||
PP_Ent *parent = PP_EntFromKey(ss, ent->parent);
|
||||
if (parent->valid)
|
||||
{
|
||||
Unlink(ent);
|
||||
PP_Unlink(ent);
|
||||
}
|
||||
ReleaseRaw(ent);
|
||||
PP_ReleaseRawEnt(ent);
|
||||
}
|
||||
|
||||
void ReleaseAllWithProp(Snapshot *ss, Prop prop)
|
||||
void PP_ReleaseAllWithProp(PP_Snapshot *ss, PP_Prop prop)
|
||||
{
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
|
||||
Entity **ents_to_release = PushDry(scratch.arena, Entity *);
|
||||
PP_Ent **ents_to_release = PushDry(scratch.arena, PP_Ent *);
|
||||
u64 ents_to_release_count = 0;
|
||||
for (u64 ent_index = 0; ent_index < ss->num_ents_reserved; ++ent_index)
|
||||
{
|
||||
Entity *ent = &ss->ents[ent_index];
|
||||
if (ent->valid && HasProp(ent, prop))
|
||||
PP_Ent *ent = &ss->ents[ent_index];
|
||||
if (ent->valid && PP_HasProp(ent, prop))
|
||||
{
|
||||
*PushStructNoZero(scratch.arena, Entity *) = ent;
|
||||
*PushStructNoZero(scratch.arena, PP_Ent *) = ent;
|
||||
++ents_to_release_count;
|
||||
}
|
||||
}
|
||||
@ -135,10 +135,10 @@ void ReleaseAllWithProp(Snapshot *ss, Prop prop)
|
||||
* child entities will be released along with parent anyway) */
|
||||
for (u64 i = 0; i < ents_to_release_count; ++i)
|
||||
{
|
||||
Entity *ent = ents_to_release[i];
|
||||
if (ent->valid && !ent->is_root && !HasProp(ent, Prop_Cmd) && !HasProp(ent, Prop_Player))
|
||||
PP_Ent *ent = ents_to_release[i];
|
||||
if (ent->valid && !ent->is_root && !PP_HasProp(ent, PP_Prop_Cmd) && !PP_HasProp(ent, PP_Prop_Player))
|
||||
{
|
||||
Release(ent);
|
||||
PP_Release(ent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,22 +148,22 @@ void ReleaseAllWithProp(Snapshot *ss, Prop prop)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Activate
|
||||
|
||||
void Activate(Entity *ent, u64 current_tick)
|
||||
void PP_ActivateEnt(PP_Ent *ent, u64 current_tick)
|
||||
{
|
||||
EnableProp(ent, Prop_Active);
|
||||
PP_EnableProp(ent, PP_Prop_Active);
|
||||
ent->activation_tick = current_tick;
|
||||
++ent->continuity_gen;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Entity id
|
||||
//~ Ent id
|
||||
|
||||
u32 IndexFromEntity(Snapshot *ss, Entity *ent)
|
||||
u32 PP_IndexFromEnt(PP_Snapshot *ss, PP_Ent *ent)
|
||||
{
|
||||
return ent - ss->ents;
|
||||
}
|
||||
|
||||
Entity *EntityFromIndex(Snapshot *ss, u32 index)
|
||||
PP_Ent *PP_EntFromIndex(PP_Snapshot *ss, u32 index)
|
||||
{
|
||||
if (index > 0 && index < ss->num_ents_reserved)
|
||||
{
|
||||
@ -171,37 +171,37 @@ Entity *EntityFromIndex(Snapshot *ss, u32 index)
|
||||
}
|
||||
else
|
||||
{
|
||||
return NilEntity();
|
||||
return PP_NilEnt();
|
||||
}
|
||||
}
|
||||
|
||||
EntBin *BinFromId(Snapshot *ss, EntityId id)
|
||||
PP_EntBin *PP_EntBinFromKey(PP_Snapshot *ss, PP_EntKey id)
|
||||
{
|
||||
return &ss->id_bins[id.uid.lo % ss->num_id_bins];
|
||||
}
|
||||
|
||||
/* NOTE: This should only really happen during ent allocation (it doesn't make sense for an allocated ent's id to change) */
|
||||
void SetEntityId(Entity *ent, EntityId id)
|
||||
void PP_SetEntKey(PP_Ent *ent, PP_EntKey id)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
EntityId old_id = ent->id;
|
||||
if (!EqId(old_id, id))
|
||||
PP_Snapshot *ss = ent->ss;
|
||||
PP_EntKey old_id = ent->id;
|
||||
if (!PP_EqEntKey(old_id, id))
|
||||
{
|
||||
/* Release old from lookup */
|
||||
if (!IsNilId(old_id))
|
||||
if (!PP_IsNilEntKey(old_id))
|
||||
{
|
||||
EntBin *bin = BinFromId(ss, old_id);
|
||||
PP_EntBin *bin = PP_EntBinFromKey(ss, old_id);
|
||||
u32 prev_index = 0;
|
||||
u32 next_index = 0;
|
||||
u32 search_index = bin->first;
|
||||
Entity *prev = NilEntity();
|
||||
Entity *next = NilEntity();
|
||||
Entity *search = EntityFromIndex(ss, search_index);
|
||||
PP_Ent *prev = PP_NilEnt();
|
||||
PP_Ent *next = PP_NilEnt();
|
||||
PP_Ent *search = PP_EntFromIndex(ss, search_index);
|
||||
while (search->valid)
|
||||
{
|
||||
next_index = search->next_in_id_bin;
|
||||
next = EntityFromIndex(ss, next_index);
|
||||
if (EqId(search->id, old_id))
|
||||
next = PP_EntFromIndex(ss, next_index);
|
||||
if (PP_EqEntKey(search->id, old_id))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -234,19 +234,19 @@ void SetEntityId(Entity *ent, EntityId id)
|
||||
}
|
||||
|
||||
/* Insert new id into lookup */
|
||||
if (!IsNilId(id))
|
||||
if (!PP_IsNilEntKey(id))
|
||||
{
|
||||
#if RtcIsEnabled
|
||||
{
|
||||
Entity *existing = EntityFromId(ss, id);
|
||||
PP_Ent *existing = PP_EntFromKey(ss, id);
|
||||
/* Collision should be extremely unlikely under normal circumstances, there's probably a logic error somewhere. */
|
||||
Assert(!existing->valid);
|
||||
}
|
||||
#endif
|
||||
|
||||
EntBin *bin = BinFromId(ss, id);
|
||||
u32 ent_index = IndexFromEntity(ss, ent);
|
||||
Entity *last = EntityFromIndex(ss, bin->last);
|
||||
PP_EntBin *bin = PP_EntBinFromKey(ss, id);
|
||||
u32 ent_index = PP_IndexFromEnt(ss, ent);
|
||||
PP_Ent *last = PP_EntFromIndex(ss, bin->last);
|
||||
if (last->valid)
|
||||
{
|
||||
last->next_in_id_bin = ent_index;
|
||||
@ -265,15 +265,15 @@ void SetEntityId(Entity *ent, EntityId id)
|
||||
|
||||
}
|
||||
|
||||
Entity *EntityFromId(Snapshot *ss, EntityId id)
|
||||
PP_Ent *PP_EntFromKey(PP_Snapshot *ss, PP_EntKey id)
|
||||
{
|
||||
Entity *result = NilEntity();
|
||||
if (!IsNilId(id) && ss->valid)
|
||||
PP_Ent *result = PP_NilEnt();
|
||||
if (!PP_IsNilEntKey(id) && ss->valid)
|
||||
{
|
||||
EntBin *bin = BinFromId(ss, id);
|
||||
for (Entity *e = EntityFromIndex(ss, bin->first); e->valid; e = EntityFromIndex(ss, e->next_in_id_bin))
|
||||
PP_EntBin *bin = PP_EntBinFromKey(ss, id);
|
||||
for (PP_Ent *e = PP_EntFromIndex(ss, bin->first); e->valid; e = PP_EntFromIndex(ss, e->next_in_id_bin))
|
||||
{
|
||||
if (EqId(e->id, id))
|
||||
if (PP_EqEntKey(e->id, id))
|
||||
{
|
||||
result = e;
|
||||
break;
|
||||
@ -283,18 +283,18 @@ Entity *EntityFromId(Snapshot *ss, EntityId id)
|
||||
return result;
|
||||
}
|
||||
|
||||
EntityId RandomId(void)
|
||||
PP_EntKey PP_RandomKey(void)
|
||||
{
|
||||
EntityId result = ZI;
|
||||
PP_EntKey result = ZI;
|
||||
result.uid = UidFromTrueRand();
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Returns the deterministic id of the contact constraint ent id that should be produced from e0 & e1 colliding */
|
||||
EntityId ContactConstraintIdFromContactingIds(EntityId player_id, EntityId id0, EntityId id1)
|
||||
PP_EntKey PP_ContactConstraintKeyFromContactingKeys(PP_EntKey player_id, PP_EntKey id0, PP_EntKey id1)
|
||||
{
|
||||
EntityId result = ZI;
|
||||
result.uid = ContactBasisUid;
|
||||
PP_EntKey result = ZI;
|
||||
result.uid = PP_ContactBasisUid;
|
||||
result.uid = CombineUid(result.uid, player_id.uid);
|
||||
result.uid = CombineUid(result.uid, id0.uid);
|
||||
result.uid = CombineUid(result.uid, id1.uid);
|
||||
@ -302,10 +302,10 @@ EntityId ContactConstraintIdFromContactingIds(EntityId player_id, EntityId id0,
|
||||
}
|
||||
|
||||
/* Returns the deterministic id of the debug contact constraint ent id that should be produced from e0 & e1 colliding */
|
||||
EntityId CollisionDebugIdFromIds(EntityId player_id, EntityId id0, EntityId id1)
|
||||
PP_EntKey PP_CollisionDebugKeyFromKeys(PP_EntKey player_id, PP_EntKey id0, PP_EntKey id1)
|
||||
{
|
||||
EntityId result = ZI;
|
||||
result.uid = CollisionDebugBasisUid;
|
||||
PP_EntKey result = ZI;
|
||||
result.uid = PP_CollisionDebugBasisUid;
|
||||
result.uid = CombineUid(result.uid, player_id.uid);
|
||||
result.uid = CombineUid(result.uid, id0.uid);
|
||||
result.uid = CombineUid(result.uid, id1.uid);
|
||||
@ -313,10 +313,10 @@ EntityId CollisionDebugIdFromIds(EntityId player_id, EntityId id0, EntityId id1)
|
||||
}
|
||||
|
||||
/* Returns the deterministic id of the tile chunk that should be produced at chunk pos */
|
||||
EntityId TileChunkIdFromIndex(Vec2I32 chunk_index)
|
||||
PP_EntKey PP_TileChunkKeyFromIndex(Vec2I32 chunk_index)
|
||||
{
|
||||
EntityId result = ZI;
|
||||
result.uid = TileChunkBasisUid;
|
||||
PP_EntKey result = ZI;
|
||||
result.uid = PP_TileChunkBasisUid;
|
||||
result.uid = CombineUid(result.uid, UID(RandU64FromSeed(chunk_index.x), RandU64FromSeed(chunk_index.y)));
|
||||
return result;
|
||||
}
|
||||
@ -324,34 +324,34 @@ EntityId TileChunkIdFromIndex(Vec2I32 chunk_index)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Query
|
||||
|
||||
Entity *FirstWithProp(Snapshot *ss, Prop prop)
|
||||
PP_Ent *PP_FirstWithProp(PP_Snapshot *ss, PP_Prop prop)
|
||||
{
|
||||
u64 count = ss->num_ents_reserved;
|
||||
Entity *entities = ss->ents;
|
||||
PP_Ent *entities = ss->ents;
|
||||
for (u64 ent_index = 0; ent_index < count; ++ent_index)
|
||||
{
|
||||
Entity *ent = &entities[ent_index];
|
||||
if (ent->valid && HasProp(ent, prop))
|
||||
PP_Ent *ent = &entities[ent_index];
|
||||
if (ent->valid && PP_HasProp(ent, prop))
|
||||
{
|
||||
return ent;
|
||||
}
|
||||
}
|
||||
return NilEntity();
|
||||
return PP_NilEnt();
|
||||
}
|
||||
|
||||
Entity *FirstWithAllProps(Snapshot *ss, PropArray props)
|
||||
PP_Ent *PP_FirstWithAllProps(PP_Snapshot *ss, PP_PropArray props)
|
||||
{
|
||||
u64 count = ss->num_ents_reserved;
|
||||
Entity *entities = ss->ents;
|
||||
PP_Ent *entities = ss->ents;
|
||||
for (u64 ent_index = 0; ent_index < count; ++ent_index)
|
||||
{
|
||||
Entity *ent = &entities[ent_index];
|
||||
PP_Ent *ent = &entities[ent_index];
|
||||
if (ent->valid)
|
||||
{
|
||||
b32 all = 1;
|
||||
for (u64 i = 0; i < props.count; ++i)
|
||||
{
|
||||
if (!HasProp(ent, props.props[i]))
|
||||
if (!PP_HasProp(ent, props.props[i]))
|
||||
{
|
||||
all = 0;
|
||||
break;
|
||||
@ -363,26 +363,26 @@ Entity *FirstWithAllProps(Snapshot *ss, PropArray props)
|
||||
}
|
||||
}
|
||||
}
|
||||
return NilEntity();
|
||||
return PP_NilEnt();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Tree
|
||||
|
||||
void Link(Entity *ent, Entity *parent)
|
||||
void PP_Link(PP_Ent *ent, PP_Ent *parent)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
PP_Snapshot *ss = ent->ss;
|
||||
|
||||
Entity *old_parent = EntityFromId(ss, ent->parent);
|
||||
PP_Ent *old_parent = PP_EntFromKey(ss, ent->parent);
|
||||
if (old_parent->valid)
|
||||
{
|
||||
/* Unlink from current parent */
|
||||
Unlink(ent);
|
||||
PP_Unlink(ent);
|
||||
}
|
||||
|
||||
EntityId ent_id = ent->id;
|
||||
EntityId last_child_id = parent->last;
|
||||
Entity *last_child = EntityFromId(ss, last_child_id);
|
||||
PP_EntKey ent_id = ent->id;
|
||||
PP_EntKey last_child_id = parent->last;
|
||||
PP_Ent *last_child = PP_EntFromKey(ss, last_child_id);
|
||||
if (last_child->valid)
|
||||
{
|
||||
ent->prev = last_child_id;
|
||||
@ -407,15 +407,15 @@ void Link(Entity *ent, Entity *parent)
|
||||
ent->parent = parent->id;
|
||||
}
|
||||
|
||||
/* NOTE: Entity will be dangling after calling this, should re-link to root ent. */
|
||||
void Unlink(Entity *ent)
|
||||
/* NOTE: PP_Ent will be dangling after calling this, should re-link to root ent. */
|
||||
void PP_Unlink(PP_Ent *ent)
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
PP_Snapshot *ss = ent->ss;
|
||||
|
||||
EntityId parent_id = ent->parent;
|
||||
Entity *parent = EntityFromId(ss, parent_id);
|
||||
Entity *prev = EntityFromId(ss, ent->prev);
|
||||
Entity *next = EntityFromId(ss, ent->next);
|
||||
PP_EntKey parent_id = ent->parent;
|
||||
PP_Ent *parent = PP_EntFromKey(ss, parent_id);
|
||||
PP_Ent *prev = PP_EntFromKey(ss, ent->prev);
|
||||
PP_Ent *next = PP_EntFromKey(ss, ent->next);
|
||||
|
||||
/* Unlink from parent & siblings */
|
||||
if (prev->valid)
|
||||
@ -434,16 +434,16 @@ void Unlink(Entity *ent)
|
||||
{
|
||||
parent->last = prev->id;
|
||||
}
|
||||
ent->prev = NilEntityId;
|
||||
ent->next = NilEntityId;
|
||||
ent->prev = PP_NilEntKey;
|
||||
ent->next = PP_NilEntKey;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Xform
|
||||
|
||||
void MarkChildXformsDirty(Snapshot *ss, Entity *ent)
|
||||
void PP_MarkChildXformsDirty(PP_Snapshot *ss, PP_Ent *ent)
|
||||
{
|
||||
for (Entity *child = EntityFromId(ss, ent->first); child->valid; child = EntityFromId(ss, child->next))
|
||||
for (PP_Ent *child = PP_EntFromKey(ss, ent->first); child->valid; child = PP_EntFromKey(ss, child->next))
|
||||
{
|
||||
if (child->_is_xform_dirty)
|
||||
{
|
||||
@ -452,12 +452,12 @@ void MarkChildXformsDirty(Snapshot *ss, Entity *ent)
|
||||
else
|
||||
{
|
||||
child->_is_xform_dirty = 1;
|
||||
MarkChildXformsDirty(ss, child);
|
||||
PP_MarkChildXformsDirty(ss, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Xform XformFromEntity_(Snapshot *ss, Entity *ent)
|
||||
Xform PP_XformFromEnt_(PP_Snapshot *ss, PP_Ent *ent)
|
||||
{
|
||||
Xform xf;
|
||||
if (ent->_is_xform_dirty)
|
||||
@ -468,8 +468,8 @@ Xform XformFromEntity_(Snapshot *ss, Entity *ent)
|
||||
}
|
||||
else
|
||||
{
|
||||
Entity *parent = EntityFromId(ss, ent->parent);
|
||||
xf = XformFromEntity_(ss, parent);
|
||||
PP_Ent *parent = PP_EntFromKey(ss, ent->parent);
|
||||
xf = PP_XformFromEnt_(ss, parent);
|
||||
xf = MulXform(xf, ent->_local_xform);
|
||||
ent->_xform = xf;
|
||||
ent->_is_xform_dirty = 0;
|
||||
@ -484,7 +484,7 @@ Xform XformFromEntity_(Snapshot *ss, Entity *ent)
|
||||
return xf;
|
||||
}
|
||||
|
||||
Xform XformFromEntity(Entity *ent)
|
||||
Xform PP_XformFromEnt(PP_Ent *ent)
|
||||
{
|
||||
Xform xf;
|
||||
if (ent->_is_xform_dirty)
|
||||
@ -495,9 +495,9 @@ Xform XformFromEntity(Entity *ent)
|
||||
}
|
||||
else
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
Entity *parent = EntityFromId(ss, ent->parent);
|
||||
xf = XformFromEntity_(ss, parent);
|
||||
PP_Snapshot *ss = ent->ss;
|
||||
PP_Ent *parent = PP_EntFromKey(ss, ent->parent);
|
||||
xf = PP_XformFromEnt_(ss, parent);
|
||||
xf = MulXform(xf, ent->_local_xform);
|
||||
ent->_xform = xf;
|
||||
ent->_is_xform_dirty = 0;
|
||||
@ -512,16 +512,16 @@ Xform XformFromEntity(Entity *ent)
|
||||
return xf;
|
||||
}
|
||||
|
||||
Xform LocalXformFromEntity(Entity *ent)
|
||||
Xform PP_LocalXformFromEnt(PP_Ent *ent)
|
||||
{
|
||||
return ent->_local_xform;
|
||||
}
|
||||
|
||||
void SetXform(Entity *ent, Xform xf)
|
||||
void PP_SetXform(PP_Ent *ent, Xform xf)
|
||||
{
|
||||
if (!EqXform(xf, ent->_xform))
|
||||
{
|
||||
Snapshot *ss = ent->ss;
|
||||
PP_Snapshot *ss = ent->ss;
|
||||
/* Update local xform */
|
||||
if (ent->is_top)
|
||||
{
|
||||
@ -529,95 +529,95 @@ void SetXform(Entity *ent, Xform xf)
|
||||
}
|
||||
else
|
||||
{
|
||||
Entity *parent = EntityFromId(ss, ent->parent);
|
||||
Xform parent_global = XformFromEntity_(ss, parent);
|
||||
PP_Ent *parent = PP_EntFromKey(ss, ent->parent);
|
||||
Xform parent_global = PP_XformFromEnt_(ss, parent);
|
||||
ent->_local_xform = MulXform(InvertXform(parent_global), xf);
|
||||
}
|
||||
ent->_xform = xf;
|
||||
ent->_is_xform_dirty = 0;
|
||||
MarkChildXformsDirty(ss, ent);
|
||||
PP_MarkChildXformsDirty(ss, ent);
|
||||
}
|
||||
}
|
||||
|
||||
void SetLocalXform(Entity *ent, Xform xf)
|
||||
void PP_SetLocalXform(PP_Ent *ent, Xform xf)
|
||||
{
|
||||
if (!EqXform(xf, ent->_local_xform))
|
||||
{
|
||||
ent->_local_xform = xf;
|
||||
ent->_is_xform_dirty = 1;
|
||||
MarkChildXformsDirty(ent->ss, ent);
|
||||
PP_MarkChildXformsDirty(ent->ss, ent);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Movement
|
||||
|
||||
void SetLinearVelocity(Entity *ent, Vec2 velocity)
|
||||
void PP_SetLinearVelocity(PP_Ent *ent, Vec2 velocity)
|
||||
{
|
||||
if (HasProp(ent, Prop_Kinematic) || HasProp(ent, Prop_Dynamic))
|
||||
if (PP_HasProp(ent, PP_Prop_Kinematic) || PP_HasProp(ent, PP_Prop_Dynamic))
|
||||
{
|
||||
ent->linear_velocity = ClampVec2Len(velocity, SIM_MAX_LINEAR_VELOCITY);
|
||||
}
|
||||
}
|
||||
|
||||
void SetAngularVelocity(Entity *ent, f32 velocity)
|
||||
void PP_SetAngularVelocity(PP_Ent *ent, f32 velocity)
|
||||
{
|
||||
if (HasProp(ent, Prop_Kinematic) || HasProp(ent, Prop_Dynamic))
|
||||
if (PP_HasProp(ent, PP_Prop_Kinematic) || PP_HasProp(ent, PP_Prop_Dynamic))
|
||||
{
|
||||
ent->angular_velocity = ClampF32(velocity, -SIM_MAX_ANGULAR_VELOCITY, SIM_MAX_ANGULAR_VELOCITY);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyLinearImpulse(Entity *ent, Vec2 impulse, Vec2 point)
|
||||
void PP_ApplyLinearImpulse(PP_Ent *ent, Vec2 impulse, Vec2 point)
|
||||
{
|
||||
if (HasProp(ent, Prop_Dynamic))
|
||||
if (PP_HasProp(ent, PP_Prop_Dynamic))
|
||||
{
|
||||
Xform xf = XformFromEntity(ent);
|
||||
Xform xf = PP_XformFromEnt(ent);
|
||||
Vec2 center = xf.og;
|
||||
f32 scale = AbsF32(DeterminantFromXform(xf));
|
||||
f32 inv_mass = 1.f / (ent->mass_unscaled * scale);
|
||||
f32 inv_inertia = 1.f / (ent->inertia_unscaled * scale);
|
||||
|
||||
Vec2 vcp = SubVec2(point, center);
|
||||
SetLinearVelocity(ent, AddVec2(ent->linear_velocity, MulVec2(impulse, inv_mass)));
|
||||
SetAngularVelocity(ent, WedgeVec2(vcp, impulse) * inv_inertia);
|
||||
PP_SetLinearVelocity(ent, AddVec2(ent->linear_velocity, MulVec2(impulse, inv_mass)));
|
||||
PP_SetAngularVelocity(ent, WedgeVec2(vcp, impulse) * inv_inertia);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyLinearImpulseToCenter(Entity *ent, Vec2 impulse)
|
||||
void PP_ApplyLinearImpulseToCenter(PP_Ent *ent, Vec2 impulse)
|
||||
{
|
||||
if (HasProp(ent, Prop_Dynamic))
|
||||
if (PP_HasProp(ent, PP_Prop_Dynamic))
|
||||
{
|
||||
Xform xf = XformFromEntity(ent);
|
||||
Xform xf = PP_XformFromEnt(ent);
|
||||
f32 scale = AbsF32(DeterminantFromXform(xf));
|
||||
f32 inv_mass = 1.f / (ent->mass_unscaled * scale);
|
||||
|
||||
SetLinearVelocity(ent, AddVec2(ent->linear_velocity, MulVec2(impulse, inv_mass)));
|
||||
PP_SetLinearVelocity(ent, AddVec2(ent->linear_velocity, MulVec2(impulse, inv_mass)));
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyForceToCenter(Entity *ent, Vec2 force)
|
||||
void PP_ApplyForceToCenter(PP_Ent *ent, Vec2 force)
|
||||
{
|
||||
if (HasProp(ent, Prop_Dynamic))
|
||||
if (PP_HasProp(ent, PP_Prop_Dynamic))
|
||||
{
|
||||
ent->force = AddVec2(ent->force, force);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyAngularImpulse(Entity *ent, f32 impulse)
|
||||
void PP_ApplyAngularImpulse(PP_Ent *ent, f32 impulse)
|
||||
{
|
||||
if (HasProp(ent, Prop_Dynamic))
|
||||
if (PP_HasProp(ent, PP_Prop_Dynamic))
|
||||
{
|
||||
Xform xf = XformFromEntity(ent);
|
||||
Xform xf = PP_XformFromEnt(ent);
|
||||
f32 scale = AbsF32(DeterminantFromXform(xf));
|
||||
f32 inv_inertia = 1.f / (ent->inertia_unscaled * scale);
|
||||
SetAngularVelocity(ent, ent->angular_velocity + impulse * inv_inertia);
|
||||
PP_SetAngularVelocity(ent, ent->angular_velocity + impulse * inv_inertia);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyTorque(Entity *ent, f32 torque)
|
||||
void PP_ApplyTorque(PP_Ent *ent, f32 torque)
|
||||
{
|
||||
if (HasProp(ent, Prop_Dynamic))
|
||||
if (PP_HasProp(ent, PP_Prop_Dynamic))
|
||||
{
|
||||
ent->torque += torque;
|
||||
}
|
||||
@ -626,33 +626,33 @@ void ApplyTorque(Entity *ent, f32 torque)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Tile
|
||||
|
||||
Entity *TileChunkFromChunkIndex(Snapshot *ss, Vec2I32 chunk_index)
|
||||
PP_Ent *PP_TileChunkFromChunkIndex(PP_Snapshot *ss, Vec2I32 chunk_index)
|
||||
{
|
||||
EntityId chunk_id = TileChunkIdFromIndex(chunk_index);
|
||||
Entity *chunk_ent = EntityFromId(ss, chunk_id);
|
||||
PP_EntKey chunk_id = PP_TileChunkKeyFromIndex(chunk_index);
|
||||
PP_Ent *chunk_ent = PP_EntFromKey(ss, chunk_id);
|
||||
return chunk_ent;
|
||||
}
|
||||
|
||||
Entity *TileChunkFromWorldTileIndex(Snapshot *ss, Vec2I32 world_tile_index)
|
||||
PP_Ent *PP_TileChunkFromWorldTileIndex(PP_Snapshot *ss, Vec2I32 world_tile_index)
|
||||
{
|
||||
Vec2I32 chunk_index = TileChunkIndexFromWorldTileIndex(world_tile_index);
|
||||
Entity *chunk_ent = TileChunkFromChunkIndex(ss, chunk_index);
|
||||
Vec2I32 chunk_index = PP_TileChunkIndexFromWorldTileIndex(world_tile_index);
|
||||
PP_Ent *chunk_ent = PP_TileChunkFromChunkIndex(ss, chunk_index);
|
||||
return chunk_ent;
|
||||
}
|
||||
|
||||
TileKind TileKindFromChunk(Entity *chunk_ent, Vec2I32 local_tile_index)
|
||||
PP_TileKind PP_TileKindFromChunk(PP_Ent *chunk_ent, Vec2I32 local_tile_index)
|
||||
{
|
||||
TileKind result = chunk_ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)];
|
||||
PP_TileKind result = chunk_ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)];
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Lerp
|
||||
|
||||
void LerpEntity(Entity *e, Entity *e0, Entity *e1, f64 blend)
|
||||
void PP_LerpEnt(PP_Ent *e, PP_Ent *e0, PP_Ent *e1, f64 blend)
|
||||
{
|
||||
if (IsValidAndActive(e0) && IsValidAndActive(e1)
|
||||
&& EqId(e0->id, e1->id)
|
||||
if (PP_IsValidAndActive(e0) && PP_IsValidAndActive(e1)
|
||||
&& PP_EqEntKey(e0->id, e1->id)
|
||||
&& e0->continuity_gen == e1->continuity_gen)
|
||||
{
|
||||
e->_local_xform = LerpXform(e0->_local_xform, e1->_local_xform, blend);
|
||||
@ -660,9 +660,9 @@ void LerpEntity(Entity *e, Entity *e0, Entity *e1, f64 blend)
|
||||
if (e->is_top)
|
||||
{
|
||||
/* TODO: Cache parent & child xforms in sim */
|
||||
Xform e0_xf = XformFromEntity(e0);
|
||||
Xform e1_xf = XformFromEntity(e1);
|
||||
SetXform(e, LerpXform(e0_xf, e1_xf, blend));
|
||||
Xform e0_xf = PP_XformFromEnt(e0);
|
||||
Xform e1_xf = PP_XformFromEnt(e1);
|
||||
PP_SetXform(e, LerpXform(e0_xf, e1_xf, blend));
|
||||
}
|
||||
|
||||
e->control_force = LerpF32(e0->control_force, e1->control_force, blend);
|
||||
@ -691,35 +691,35 @@ void LerpEntity(Entity *e, Entity *e0, Entity *e1, f64 blend)
|
||||
//~ Sync
|
||||
|
||||
/* Walks a local & remote ent tree and allocates any missing net dst ents from remote src ents */
|
||||
void CreateMissingEntitiesFromSnapshots(Entity *local_parent, Entity *remote, EntityId remote_player)
|
||||
void PP_CreateMissingEntsFromSnapshots(PP_Ent *local_parent, PP_Ent *remote, PP_EntKey remote_player)
|
||||
{
|
||||
__prof;
|
||||
if (HasProp(remote, Prop_SyncSrc))
|
||||
if (PP_HasProp(remote, PP_Prop_SyncSrc))
|
||||
{
|
||||
Snapshot *local_ss = local_parent->ss;
|
||||
Snapshot *remote_ss = remote->ss;
|
||||
PP_Snapshot *local_ss = local_parent->ss;
|
||||
PP_Snapshot *remote_ss = remote->ss;
|
||||
|
||||
EntityId id = remote->id;
|
||||
Entity *local_ent = EntityFromId(local_ss, id);
|
||||
PP_EntKey id = remote->id;
|
||||
PP_Ent *local_ent = PP_EntFromKey(local_ss, id);
|
||||
if (!local_ent->valid)
|
||||
{
|
||||
local_ent = AcquireSyncDst(local_parent, id, remote_player);
|
||||
local_ent = PP_AcquireSyncDstEnt(local_parent, id, remote_player);
|
||||
}
|
||||
for (Entity *remote_child = EntityFromId(remote_ss, remote->first); remote_child->valid; remote_child = EntityFromId(remote_ss, remote_child->next))
|
||||
for (PP_Ent *remote_child = PP_EntFromKey(remote_ss, remote->first); remote_child->valid; remote_child = PP_EntFromKey(remote_ss, remote_child->next))
|
||||
{
|
||||
CreateMissingEntitiesFromSnapshots(local_ent, remote_child, remote_player);
|
||||
PP_CreateMissingEntsFromSnapshots(local_ent, remote_child, remote_player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Copies data between two synced entities */
|
||||
void SyncEntity(Entity *local, Entity *remote)
|
||||
void PP_SyncEnt(PP_Ent *local, PP_Ent *remote)
|
||||
{
|
||||
Entity old = *local;
|
||||
PP_Ent old = *local;
|
||||
CopyStruct(local, remote);
|
||||
|
||||
/* Why would 2 ents w/ different uids ever be synced? */
|
||||
Assert(EqId(local->id, old.id));
|
||||
Assert(PP_EqEntKey(local->id, old.id));
|
||||
|
||||
local->ss = old.ss;
|
||||
local->id = old.id;
|
||||
@ -738,8 +738,8 @@ void SyncEntity(Entity *local, Entity *remote)
|
||||
local->prev_in_id_bin = old.prev_in_id_bin;
|
||||
local->next_free = old.next_free;
|
||||
|
||||
DisableProp(local, Prop_SyncSrc);
|
||||
EnableProp(local, Prop_SyncDst);
|
||||
PP_DisableProp(local, PP_Prop_SyncSrc);
|
||||
PP_EnableProp(local, PP_Prop_SyncDst);
|
||||
}
|
||||
|
||||
#if 1
|
||||
@ -747,9 +747,9 @@ void SyncEntity(Entity *local, Entity *remote)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Encode
|
||||
|
||||
void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1)
|
||||
void PP_EncodeEnt(BB_Writer *bw, PP_Ent *e0, PP_Ent *e1)
|
||||
{
|
||||
Snapshot *ss = e1->ss;
|
||||
PP_Snapshot *ss = e1->ss;
|
||||
/* FIXME: Things like xforms need to be retreived manually rather than memcopied. */
|
||||
|
||||
/* TODO: Granular delta encoding */
|
||||
@ -775,9 +775,9 @@ void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Decode
|
||||
|
||||
void DecodeEntity(BB_Reader *br, Entity *e)
|
||||
void PP_DecodeEnt(BB_Reader *br, PP_Ent *e)
|
||||
{
|
||||
Snapshot *old_ss = e->ss;
|
||||
PP_Snapshot *old_ss = e->ss;
|
||||
{
|
||||
u64 pos = 0;
|
||||
while (pos < sizeof(*e))
|
||||
@ -801,9 +801,9 @@ void DecodeEntity(BB_Reader *br, Entity *e)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Encode
|
||||
|
||||
void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1)
|
||||
void PP_EncodeEnt(BB_Writer *bw, PP_Ent *e0, PP_Ent *e1)
|
||||
{
|
||||
Snapshot *ss = e1->ss;
|
||||
PP_Snapshot *ss = e1->ss;
|
||||
|
||||
|
||||
/* FIXME: Things like xforms need to be retreived manually rather than memcopied.
|
||||
@ -837,9 +837,9 @@ void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Decode
|
||||
|
||||
void DecodeEntity(BB_Reader *br, Entity *e)
|
||||
void PP_DecodeEnt(BB_Reader *br, PP_Ent *e)
|
||||
{
|
||||
Entity decoded = *e;
|
||||
PP_Ent decoded = *e;
|
||||
{
|
||||
u64 pos = 0;
|
||||
while (pos < sizeof(decoded))
|
||||
@ -856,13 +856,13 @@ void DecodeEntity(BB_Reader *br, Entity *e)
|
||||
}
|
||||
decoded.ss = e->ss;
|
||||
|
||||
EntityId old_id = e->id;
|
||||
EntityId new_id = decoded.id;
|
||||
PP_EntKey old_id = e->id;
|
||||
PP_EntKey new_id = decoded.id;
|
||||
CopyStruct(e, &decoded);
|
||||
e->id = old_id;
|
||||
if (!EqId(old_id, new_id))
|
||||
if (!PP_EqEntKey(old_id, new_id))
|
||||
{
|
||||
SetEntityId(e, new_id);
|
||||
PP_SetEntKey(e, new_id);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
352
src/pp/pp_ent.h
352
src/pp/pp_ent.h
@ -1,78 +1,78 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Entity props
|
||||
//~ Ent props
|
||||
|
||||
Enum(Prop)
|
||||
Enum(PP_Prop)
|
||||
{
|
||||
Prop_Active,
|
||||
Prop_Release,
|
||||
PP_Prop_Active,
|
||||
PP_Prop_Release,
|
||||
|
||||
Prop_SyncSrc, /* This entity is networked to other clients */
|
||||
Prop_SyncDst, /* This entity is not locally created, and will sync with incoming net src ents */
|
||||
PP_Prop_SyncSrc, /* This entity is networked to other clients */
|
||||
PP_Prop_SyncDst, /* This entity is not locally created, and will sync with incoming net src ents */
|
||||
|
||||
Prop_Player,
|
||||
Prop_IsMaster,
|
||||
PP_Prop_Player,
|
||||
PP_Prop_IsMaster,
|
||||
|
||||
Prop_Cmd,
|
||||
PP_Prop_Cmd,
|
||||
|
||||
Prop_TileChunk,
|
||||
Prop_Wall,
|
||||
PP_Prop_TileChunk,
|
||||
PP_Prop_Wall,
|
||||
|
||||
/* Physics collision */
|
||||
Prop_Sensor, /* This entity's collisions generate contacts */
|
||||
Prop_Solid, /* This entity's collisions generate contacts to be solved by the physics system (overrides Prop_Sensor) */
|
||||
Prop_Toi, /* This entity's collisions are processed using TOI (time of impact) for precise collisions */
|
||||
PP_Prop_Sensor, /* This entity's collisions generate contacts */
|
||||
PP_Prop_Solid, /* This entity's collisions generate contacts to be solved by the physics system (overrides PP_Prop_Sensor) */
|
||||
PP_Prop_Toi, /* This entity's collisions are processed using TOI (time of impact) for precise collisions */
|
||||
|
||||
/* Physics movement */
|
||||
Prop_Kinematic, /* This entity reacts to velocity */
|
||||
Prop_Dynamic, /* This entity reacts to velocity and forces (overrides Prop_Kinematic) */
|
||||
PP_Prop_Kinematic, /* This entity reacts to velocity */
|
||||
PP_Prop_Dynamic, /* This entity reacts to velocity and forces (overrides PP_Prop_Kinematic) */
|
||||
|
||||
Prop_Controlled,
|
||||
PP_Prop_Controlled,
|
||||
|
||||
Prop_CollisionDebug,
|
||||
Prop_ContactConstraint,
|
||||
Prop_MotorJoint,
|
||||
Prop_MouseJoint,
|
||||
Prop_WeldJoint,
|
||||
PP_Prop_CollisionDebug,
|
||||
PP_Prop_ContactConstraint,
|
||||
PP_Prop_MotorJoint,
|
||||
PP_Prop_MouseJoint,
|
||||
PP_Prop_WeldJoint,
|
||||
|
||||
Prop_Camera,
|
||||
Prop_ActiveCamera,
|
||||
PP_Prop_Camera,
|
||||
PP_Prop_ActiveCamera,
|
||||
|
||||
Prop_Bullet,
|
||||
Prop_Smg,
|
||||
Prop_Launcher,
|
||||
Prop_Chucker,
|
||||
PP_Prop_Bullet,
|
||||
PP_Prop_Smg,
|
||||
PP_Prop_Launcher,
|
||||
PP_Prop_Chucker,
|
||||
|
||||
Prop_ChuckerZone,
|
||||
PP_Prop_ChuckerZone,
|
||||
|
||||
Prop_Explosion,
|
||||
PP_Prop_Explosion,
|
||||
|
||||
Prop_Tracer,
|
||||
PP_Prop_Tracer,
|
||||
|
||||
Prop_Quake,
|
||||
PP_Prop_Quake,
|
||||
|
||||
Prop_Attached,
|
||||
PP_Prop_Attached,
|
||||
|
||||
/* Test props */
|
||||
|
||||
Prop_Test,
|
||||
Prop_SoundEmitterTest,
|
||||
Prop_LightTest,
|
||||
PP_Prop_Test,
|
||||
PP_Prop_SoundEmitterTest,
|
||||
PP_Prop_LightTest,
|
||||
|
||||
Prop_Count
|
||||
PP_Prop_Count
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Entity
|
||||
//~ Ent
|
||||
|
||||
Struct(Entity)
|
||||
Struct(PP_Ent)
|
||||
{
|
||||
Snapshot *ss;
|
||||
PP_Snapshot *ss;
|
||||
|
||||
//- Metadata
|
||||
|
||||
b32 valid; /* Is this ent allocated in memory that can be written to (can always be read) */
|
||||
EntityId id;
|
||||
u64 props[(Prop_Count + 63) / 64];
|
||||
PP_EntKey id;
|
||||
u64 props[(PP_Prop_Count + 63) / 64];
|
||||
u64 continuity_gen;
|
||||
|
||||
/* Is this the root ent */
|
||||
@ -82,14 +82,14 @@ Struct(Entity)
|
||||
b32 is_top;
|
||||
|
||||
/* The id of the top level parent of the ent tree (if ent is top then this point to itself) */
|
||||
EntityId top;
|
||||
PP_EntKey top;
|
||||
|
||||
/* Tree */
|
||||
EntityId parent;
|
||||
EntityId next;
|
||||
EntityId prev;
|
||||
EntityId first;
|
||||
EntityId last;
|
||||
PP_EntKey parent;
|
||||
PP_EntKey next;
|
||||
PP_EntKey prev;
|
||||
PP_EntKey first;
|
||||
PP_EntKey last;
|
||||
|
||||
/* Lists keyed by index in snapshot ent array */
|
||||
u32 next_in_id_bin;
|
||||
@ -98,14 +98,14 @@ Struct(Entity)
|
||||
|
||||
//- Sync
|
||||
|
||||
/* Prop_SyncSrc */
|
||||
/* Prop_SyncDst */
|
||||
/* PP_Prop_SyncSrc */
|
||||
/* PP_Prop_SyncDst */
|
||||
|
||||
/* Id of the player that owns simulation for this entity */
|
||||
EntityId owner;
|
||||
PP_EntKey owner;
|
||||
|
||||
/* Id of the player that should predict simulation of this this entity locally */
|
||||
EntityId predictor;
|
||||
PP_EntKey predictor;
|
||||
|
||||
//- Position
|
||||
|
||||
@ -126,31 +126,31 @@ Struct(Entity)
|
||||
|
||||
//- Cmd
|
||||
|
||||
/* Prop_Cmd */
|
||||
/* PP_Prop_Cmd */
|
||||
|
||||
CmdKind cmd_kind;
|
||||
EntityId cmd_player;
|
||||
PP_CmdKind cmd_kind;
|
||||
PP_EntKey cmd_player;
|
||||
|
||||
/* FIXME: Lerp */
|
||||
|
||||
/* Control cmd */
|
||||
ControlData cmd_control;
|
||||
EntityId cmd_control_hovered_ent;
|
||||
PP_ControlData cmd_control;
|
||||
PP_EntKey cmd_control_hovered_ent;
|
||||
|
||||
/* Chat cmd */
|
||||
//String cmd_chat_msg;
|
||||
|
||||
//- Chat
|
||||
|
||||
/* Prop_CHAT */
|
||||
/* PP_Prop_Chat */
|
||||
|
||||
EntityId chat_player;
|
||||
PP_EntKey chat_player;
|
||||
//String chat_msg;
|
||||
|
||||
|
||||
//- Tile
|
||||
|
||||
/* Prop_TileChunk */
|
||||
/* PP_Prop_TileChunk */
|
||||
|
||||
/* FIXME: Move out of here */
|
||||
u8 tile_chunk_tiles[SIM_TILES_PER_CHUNK_SQRT * SIM_TILES_PER_CHUNK_SQRT];
|
||||
@ -158,20 +158,20 @@ Struct(Entity)
|
||||
|
||||
//- Client
|
||||
|
||||
/* Prop_Player */
|
||||
/* PP_Prop_Player */
|
||||
|
||||
/* FIXME: Lerp */
|
||||
|
||||
ClientHandle player_client_handle; /* The client handle on the master sim's machine */
|
||||
PP_ClientKey player_client_handle; /* The client key on the master sim's machine */
|
||||
|
||||
ControlData player_control;
|
||||
PP_ControlData player_control;
|
||||
Vec2 player_cursor_pos;
|
||||
|
||||
EntityId player_hovered_ent;
|
||||
EntityId player_control_ent;
|
||||
EntityId player_camera_ent;
|
||||
PP_EntKey player_hovered_ent;
|
||||
PP_EntKey player_control_ent;
|
||||
PP_EntKey player_camera_ent;
|
||||
|
||||
EntityId player_dbg_drag_joint_ent;
|
||||
PP_EntKey player_dbg_drag_joint_ent;
|
||||
b32 player_dbg_drag_start;
|
||||
b32 player_dbg_drag_stop;
|
||||
|
||||
@ -188,41 +188,41 @@ Struct(Entity)
|
||||
ContactDebugData collision_debug_data;
|
||||
#endif
|
||||
|
||||
SpaceEntryHandle space_handle;
|
||||
PP_SpaceEntryKey space_handle;
|
||||
|
||||
//- Constraints / joints
|
||||
|
||||
/* Prop_CONSTRAINT_CONTACT */
|
||||
ContactConstraint contact_constraint_data;
|
||||
/* PP_Prop_ContactConstraint */
|
||||
PP_ContactConstraint contact_constraint_data;
|
||||
|
||||
/* Prop_MotorJoint */
|
||||
MotorJoint motor_joint_data;
|
||||
/* PP_Prop_MotorJoint */
|
||||
PP_MotorJoint motor_joint_data;
|
||||
|
||||
/* Prop_MouseJoint */
|
||||
MouseJoint mouse_joint_data;
|
||||
/* PP_Prop_MouseJoint */
|
||||
PP_MouseJoint mouse_joint_data;
|
||||
|
||||
/* Prop_WeldJoint */
|
||||
WeldJoint weld_joint_data;
|
||||
/* PP_Prop_WeldJoint */
|
||||
PP_WeldJoint weld_joint_data;
|
||||
|
||||
//- Control
|
||||
|
||||
/* Prop_Controlled */
|
||||
/* PP_Prop_Controlled */
|
||||
|
||||
EntityId controlling_player;
|
||||
PP_EntKey controlling_player;
|
||||
|
||||
f32 control_force; /* How much force is applied to achieve desired control movement */
|
||||
f32 control_force_max_speed; /* Maximum linear velocity achieved by force (m/s) */
|
||||
|
||||
f32 control_torque; /* How much torque is applied when turning towards desired focus */
|
||||
|
||||
ControlData control;
|
||||
PP_ControlData control;
|
||||
|
||||
EntityId move_joint;
|
||||
EntityId aim_joint;
|
||||
PP_EntKey move_joint;
|
||||
PP_EntKey aim_joint;
|
||||
|
||||
//- Physics
|
||||
|
||||
/* Prop_Dynamic */
|
||||
/* PP_Prop_Dynamic */
|
||||
|
||||
//f32 density; /* Density in kg/m^2 */
|
||||
|
||||
@ -231,11 +231,11 @@ Struct(Entity)
|
||||
f32 mass_unscaled; /* Mass of ent in kg before any transformations */
|
||||
f32 inertia_unscaled; /* Inertia of ent in kg*m^2 before any transformations */
|
||||
|
||||
EntityId ground_friction_joint;
|
||||
PP_EntKey ground_friction_joint;
|
||||
f32 linear_ground_friction;
|
||||
f32 angular_ground_friction;
|
||||
|
||||
/* Use SetLinearVelocity & SetAngularVelocity to set */
|
||||
/* Use PP_SetLinearVelocity & PP_SetAngularVelocity to set */
|
||||
Vec2 linear_velocity; /* m/s */
|
||||
f32 angular_velocity; /* rad/s */
|
||||
|
||||
@ -258,32 +258,32 @@ Struct(Entity)
|
||||
|
||||
//- Animation
|
||||
|
||||
/* Prop_ANIMATING */
|
||||
/* PP_Prop_Animating */
|
||||
i64 animation_last_frame_change_time_ns;
|
||||
u32 animation_frame;
|
||||
|
||||
//- Attachment
|
||||
|
||||
/* Prop_Attached */
|
||||
/* PP_Prop_Attached */
|
||||
/* Slice name on the parent ent's sprite to attach to */
|
||||
String attach_slice;
|
||||
|
||||
//- Equip
|
||||
|
||||
EntityId equipped;
|
||||
PP_EntKey equipped;
|
||||
|
||||
//- Chucker
|
||||
|
||||
/* Prop_Chucker */
|
||||
/* PP_Prop_Chucker */
|
||||
|
||||
EntityId chucker_zone;
|
||||
EntityId chucker_joint;
|
||||
PP_EntKey chucker_zone;
|
||||
PP_EntKey chucker_joint;
|
||||
|
||||
//- Chucker zone
|
||||
|
||||
/* Prop_ChuckerZone */
|
||||
/* PP_Prop_ChuckerZone */
|
||||
|
||||
EntityId chucker_zone_ent;
|
||||
PP_EntKey chucker_zone_ent;
|
||||
u64 chucker_zone_ent_tick;
|
||||
|
||||
//- Triggerable
|
||||
@ -303,13 +303,13 @@ Struct(Entity)
|
||||
i64 triggered_count;
|
||||
|
||||
/* Other triggers to activate when this entity has been triggered */
|
||||
//EntityId trigger_out_left;
|
||||
//EntityId trigger_out_right;
|
||||
//PP_EntKey trigger_out_left;
|
||||
//PP_EntKey trigger_out_right;
|
||||
|
||||
//- Bullet
|
||||
|
||||
EntityId bullet_src;
|
||||
EntityId bullet_tracer;
|
||||
PP_EntKey bullet_src;
|
||||
PP_EntKey bullet_tracer;
|
||||
Vec2 bullet_src_pos;
|
||||
Vec2 bullet_src_dir;
|
||||
f32 bullet_launch_velocity;
|
||||
@ -325,7 +325,7 @@ Struct(Entity)
|
||||
|
||||
//- Tracer
|
||||
|
||||
/* Prop_Tracer */
|
||||
/* PP_Prop_Tracer */
|
||||
|
||||
Vec2 tracer_start;
|
||||
Vec2 tracer_start_velocity;
|
||||
@ -337,7 +337,7 @@ Struct(Entity)
|
||||
|
||||
//- Quake
|
||||
|
||||
/* Prop_Quake */
|
||||
/* PP_Prop_Quake */
|
||||
|
||||
f32 quake_intensity;
|
||||
f32 quake_frequency;
|
||||
@ -345,20 +345,20 @@ Struct(Entity)
|
||||
|
||||
//- Testing
|
||||
|
||||
/* Prop_Test */
|
||||
/* PP_Prop_Test */
|
||||
b32 test_initialized;
|
||||
Xform test_start_local_xform;
|
||||
Xform test_start_sprite_xform;
|
||||
|
||||
/* Prop_SoundEmitterTest */
|
||||
/* PP_Prop_SoundEmitterTest */
|
||||
String sound_name;
|
||||
MIX_TrackDesc sound_desc;
|
||||
MIX_Handle sound_handle;
|
||||
|
||||
//- Camera
|
||||
|
||||
/* Prop_Camera */
|
||||
EntityId camera_follow;
|
||||
/* PP_Prop_Camera */
|
||||
PP_EntKey camera_follow;
|
||||
Xform camera_quad_xform;
|
||||
f32 camera_lerp; /* Rate at which camera xform approaches target xform */
|
||||
|
||||
@ -369,103 +369,103 @@ Struct(Entity)
|
||||
f32 shake;
|
||||
};
|
||||
|
||||
Struct(EntityArray)
|
||||
Struct(PP_EntArray)
|
||||
{
|
||||
Entity *ents;
|
||||
PP_Ent *ents;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
Struct(PropArray)
|
||||
Struct(PP_PropArray)
|
||||
{
|
||||
Prop *props;
|
||||
PP_Prop *props;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
Struct(EntBin)
|
||||
Struct(PP_EntBin)
|
||||
{
|
||||
u32 first;
|
||||
u32 last;
|
||||
};
|
||||
|
||||
Inline Entity *NilEntity(void)
|
||||
Inline PP_Ent *PP_NilEnt(void)
|
||||
{
|
||||
extern Readonly Entity **_g_sim_ent_nil;
|
||||
return *_g_sim_ent_nil;
|
||||
extern Readonly PP_Ent **PP_nil_ent;
|
||||
return *PP_nil_ent;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Id types
|
||||
|
||||
#define NilEntityId ((EntityId) { UID(0, 0) })
|
||||
#define RootEntityId ((EntityId) { UID(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa) })
|
||||
#define PP_NilEntKey ((PP_EntKey) { UID(0, 0) })
|
||||
#define PP_RootEntKey ((PP_EntKey) { UID(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa) })
|
||||
|
||||
/* Id magic number constants (to be used in conjunction with ent ids in deterministic id combinations) */
|
||||
#define TileChunkBasisUid (UID(0x3ce42de071dd226b, 0x9b566f7df30c813a))
|
||||
#define ContactBasisUid (UID(0x6a2a5d2dbecf534f, 0x0a8ca7c372a015af))
|
||||
#define CollisionDebugBasisUid (UID(0x302c01182013bb02, 0x570bd270399d11a5))
|
||||
#define PP_TileChunkBasisUid (UID(0x3ce42de071dd226b, 0x9b566f7df30c813a))
|
||||
#define PP_ContactBasisUid (UID(0x6a2a5d2dbecf534f, 0x0a8ca7c372a015af))
|
||||
#define PP_CollisionDebugBasisUid (UID(0x302c01182013bb02, 0x570bd270399d11a5))
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Id helpers
|
||||
|
||||
Inline b32 EqId(EntityId a, EntityId b)
|
||||
Inline b32 PP_EqEntKey(PP_EntKey a, PP_EntKey b)
|
||||
{
|
||||
return EqUid(a.uid, b.uid);
|
||||
}
|
||||
|
||||
Inline b32 IsNilId(EntityId id)
|
||||
Inline b32 PP_IsNilEntKey(PP_EntKey id)
|
||||
{
|
||||
return EqUid(id.uid, NilEntityId.uid);
|
||||
return EqUid(id.uid, PP_NilEntKey.uid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Property helpers
|
||||
|
||||
Inline void EnableProp(Entity *ent, Prop prop)
|
||||
Inline void PP_EnableProp(PP_Ent *ent, PP_Prop prop)
|
||||
{
|
||||
u64 index = prop / 64;
|
||||
u64 bit = prop % 64;
|
||||
ent->props[index] |= ((u64)1 << bit);
|
||||
}
|
||||
|
||||
Inline void DisableProp(Entity *ent, Prop prop)
|
||||
Inline void PP_DisableProp(PP_Ent *ent, PP_Prop prop)
|
||||
{
|
||||
u64 index = prop / 64;
|
||||
u64 bit = prop % 64;
|
||||
ent->props[index] &= ~((u64)1 << bit);
|
||||
}
|
||||
|
||||
Inline b32 HasProp(Entity *ent, Prop prop)
|
||||
Inline b32 PP_HasProp(PP_Ent *ent, PP_Prop prop)
|
||||
{
|
||||
u64 index = prop / 64;
|
||||
u64 bit = prop % 64;
|
||||
return !!(ent->props[index] & ((u64)1 << bit));
|
||||
}
|
||||
|
||||
Inline b32 IsValidAndActive(Entity *ent)
|
||||
Inline b32 PP_IsValidAndActive(PP_Ent *ent)
|
||||
{
|
||||
return ent->valid && HasProp(ent, Prop_Active);
|
||||
return ent->valid && PP_HasProp(ent, PP_Prop_Active);
|
||||
}
|
||||
|
||||
Inline b32 ShouldPredict(Entity *ent)
|
||||
Inline b32 PP_ShouldPredict(PP_Ent *ent)
|
||||
{
|
||||
return EqId(ent->predictor, ent->ss->local_player);
|
||||
return PP_EqEntKey(ent->predictor, ent->ss->local_player);
|
||||
}
|
||||
|
||||
Inline b32 IsOwner(Entity *ent)
|
||||
Inline b32 PP_IsOwner(PP_Ent *ent)
|
||||
{
|
||||
return EqId(ent->owner, ent->ss->local_player);
|
||||
return PP_EqEntKey(ent->owner, ent->ss->local_player);
|
||||
}
|
||||
|
||||
Inline b32 ShouldSimulate(Entity *ent)
|
||||
Inline b32 PP_ShouldSimulate(PP_Ent *ent)
|
||||
{
|
||||
b32 result = 0;
|
||||
if (IsValidAndActive(ent))
|
||||
if (PP_IsValidAndActive(ent))
|
||||
{
|
||||
result = 1;
|
||||
if (HasProp(ent, Prop_SyncDst))
|
||||
if (PP_HasProp(ent, PP_Prop_SyncDst))
|
||||
{
|
||||
EntityId local_player = ent->ss->local_player;
|
||||
result = EqId(local_player, ent->owner) || EqId(local_player, ent->predictor);
|
||||
PP_EntKey local_player = ent->ss->local_player;
|
||||
result = PP_EqEntKey(local_player, ent->owner) || PP_EqEntKey(local_player, ent->predictor);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -474,95 +474,95 @@ Inline b32 ShouldSimulate(Entity *ent)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Acquire operations
|
||||
|
||||
Entity *AcquireRaw(Snapshot *ss, Entity *parent, EntityId id);
|
||||
Entity *AcquireLocal(Entity *parent);
|
||||
Entity *AcquireLocalWithId(Entity *parent, EntityId id);
|
||||
Entity *AcquireSyncSrc(Entity *parent);
|
||||
Entity *AcquireSyncSrcWithId(Entity *parent, EntityId id);
|
||||
Entity *AcquireSyncDst(Entity *parent, EntityId ent_id, EntityId owner_id);
|
||||
PP_Ent *PP_AcquireRawEnt(PP_Snapshot *ss, PP_Ent *parent, PP_EntKey id);
|
||||
PP_Ent *PP_AcquireLocalEnt(PP_Ent *parent);
|
||||
PP_Ent *PP_AcquireLocalEntWithKey(PP_Ent *parent, PP_EntKey id);
|
||||
PP_Ent *PP_AcquireSyncSrcEnt(PP_Ent *parent);
|
||||
PP_Ent *PP_AcquireSyncSrcEntWithKey(PP_Ent *parent, PP_EntKey id);
|
||||
PP_Ent *PP_AcquireSyncDstEnt(PP_Ent *parent, PP_EntKey ent_id, PP_EntKey owner_id);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Release operations
|
||||
|
||||
void ReleaseRaw(Entity *ent);
|
||||
void Release(Entity *ent);
|
||||
void ReleaseAllWithProp(Snapshot *ss, Prop prop);
|
||||
void PP_ReleaseRawEnt(PP_Ent *ent);
|
||||
void PP_Release(PP_Ent *ent);
|
||||
void PP_ReleaseAllWithProp(PP_Snapshot *ss, PP_Prop prop);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Activate operations
|
||||
|
||||
void Activate(Entity *ent, u64 current_tick);
|
||||
void PP_ActivateEnt(PP_Ent *ent, u64 current_tick);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Id operations
|
||||
|
||||
u32 IndexFromEntity(Snapshot *ss, Entity *ent);
|
||||
Entity *EntityFromIndex(Snapshot *ss, u32 index);
|
||||
EntBin *BinFromId(Snapshot *ss, EntityId id);
|
||||
void SetEntityId(Entity *ent, EntityId id);
|
||||
Entity *EntityFromId(Snapshot *ss, EntityId id);
|
||||
EntityId RandomId(void);
|
||||
EntityId ContactConstraintIdFromContactingIds(EntityId player_id, EntityId id0, EntityId id1);
|
||||
EntityId CollisionDebugIdFromIds(EntityId player_id, EntityId id0, EntityId id1);
|
||||
EntityId TileChunkIdFromIndex(Vec2I32 chunk_start);
|
||||
u32 PP_IndexFromEnt(PP_Snapshot *ss, PP_Ent *ent);
|
||||
PP_Ent *PP_EntFromIndex(PP_Snapshot *ss, u32 index);
|
||||
PP_EntBin *PP_EntBinFromKey(PP_Snapshot *ss, PP_EntKey id);
|
||||
void PP_SetEntKey(PP_Ent *ent, PP_EntKey id);
|
||||
PP_Ent *PP_EntFromKey(PP_Snapshot *ss, PP_EntKey id);
|
||||
PP_EntKey PP_RandomKey(void);
|
||||
PP_EntKey PP_ContactConstraintKeyFromContactingKeys(PP_EntKey player_id, PP_EntKey id0, PP_EntKey id1);
|
||||
PP_EntKey PP_CollisionDebugKeyFromKeys(PP_EntKey player_id, PP_EntKey id0, PP_EntKey id1);
|
||||
PP_EntKey PP_TileChunkKeyFromIndex(Vec2I32 chunk_start);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Query operations
|
||||
|
||||
Entity *FirstWithProp(Snapshot *ss, Prop prop);
|
||||
Entity *FirstWithAllProps(Snapshot *ss, PropArray props);
|
||||
PP_Ent *PP_FirstWithProp(PP_Snapshot *ss, PP_Prop prop);
|
||||
PP_Ent *PP_FirstWithAllProps(PP_Snapshot *ss, PP_PropArray props);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Tree operations
|
||||
|
||||
void Link(Entity *parent, Entity *child);
|
||||
void Unlink(Entity *ent);
|
||||
void PP_Link(PP_Ent *parent, PP_Ent *child);
|
||||
void PP_Unlink(PP_Ent *ent);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Xform operations
|
||||
|
||||
void MarkChildXformsDirty(Snapshot *ss, Entity *ent);
|
||||
Xform XformFromEntity_(Snapshot *ss, Entity *ent);
|
||||
Xform XformFromEntity(Entity *ent);
|
||||
Xform LocalXformFromEntity(Entity *ent);
|
||||
void SetXform(Entity *ent, Xform xf);
|
||||
void SetLocalXform(Entity *ent, Xform xf);
|
||||
void PP_MarkChildXformsDirty(PP_Snapshot *ss, PP_Ent *ent);
|
||||
Xform PP_XformFromEnt_(PP_Snapshot *ss, PP_Ent *ent);
|
||||
Xform PP_XformFromEnt(PP_Ent *ent);
|
||||
Xform PP_LocalXformFromEnt(PP_Ent *ent);
|
||||
void PP_SetXform(PP_Ent *ent, Xform xf);
|
||||
void PP_SetLocalXform(PP_Ent *ent, Xform xf);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Movement operations
|
||||
|
||||
void SetLinearVelocity(Entity *ent, Vec2 velocity);
|
||||
void SetAngularVelocity(Entity *ent, f32 velocity);
|
||||
void ApplyLinearImpulse(Entity *ent, Vec2 impulse, Vec2 world_point);
|
||||
void ApplyLinearImpulseToCenter(Entity *ent, Vec2 impulse);
|
||||
void ApplyForceToCenter(Entity *ent, Vec2 force);
|
||||
void ApplyAngularImpulse(Entity *ent, f32 impulse);
|
||||
void ApplyTorque(Entity *ent, f32 torque);
|
||||
void PP_SetLinearVelocity(PP_Ent *ent, Vec2 velocity);
|
||||
void PP_SetAngularVelocity(PP_Ent *ent, f32 velocity);
|
||||
void PP_ApplyLinearImpulse(PP_Ent *ent, Vec2 impulse, Vec2 world_point);
|
||||
void PP_ApplyLinearImpulseToCenter(PP_Ent *ent, Vec2 impulse);
|
||||
void PP_ApplyForceToCenter(PP_Ent *ent, Vec2 force);
|
||||
void PP_ApplyAngularImpulse(PP_Ent *ent, f32 impulse);
|
||||
void PP_ApplyTorque(PP_Ent *ent, f32 torque);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Tile operations
|
||||
|
||||
Entity *TileChunkFromChunkIndex(Snapshot *ss, Vec2I32 chunk_index);
|
||||
Entity *TileChunkFromWorldTileIndex(Snapshot *ss, Vec2I32 world_tile_index);
|
||||
TileKind TileKindFromChunk(Entity *chunk_ent, Vec2I32 local_tile_index);
|
||||
PP_Ent *PP_TileChunkFromChunkIndex(PP_Snapshot *ss, Vec2I32 chunk_index);
|
||||
PP_Ent *PP_TileChunkFromWorldTileIndex(PP_Snapshot *ss, Vec2I32 world_tile_index);
|
||||
PP_TileKind PP_TileKindFromChunk(PP_Ent *chunk_ent, Vec2I32 local_tile_index);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Lerp operations
|
||||
|
||||
void LerpEntity(Entity *e, Entity *e0, Entity *e1, f64 blend);
|
||||
void PP_LerpEnt(PP_Ent *e, PP_Ent *e0, PP_Ent *e1, f64 blend);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Sync operations
|
||||
|
||||
void CreateMissingEntitiesFromSnapshots(Entity *local_parent, Entity *remote, EntityId remote_player);
|
||||
void SyncEntity(Entity *local, Entity *remote);
|
||||
void PP_CreateMissingEntsFromSnapshots(PP_Ent *local_parent, PP_Ent *remote, PP_EntKey remote_player);
|
||||
void PP_SyncEnt(PP_Ent *local, PP_Ent *remote);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Encode
|
||||
|
||||
void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1);
|
||||
void PP_EncodeEnt(BB_Writer *bw, PP_Ent *e0, PP_Ent *e1);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Decode
|
||||
|
||||
void DecodeEntity(BB_Reader *br, Entity *e);
|
||||
void PP_DecodeEnt(BB_Reader *br, PP_Ent *e);
|
||||
|
||||
590
src/pp/pp_phys.c
590
src/pp/pp_phys.c
File diff suppressed because it is too large
Load Diff
125
src/pp/pp_phys.h
125
src/pp/pp_phys.h
@ -1,13 +1,13 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Collision data types
|
||||
|
||||
#define ContactSpringHz 25
|
||||
#define ContactSpringDamp 10
|
||||
#define PP_ContactSpringHz 25
|
||||
#define PP_ContactSpringDamp 10
|
||||
|
||||
Struct(CollisionData)
|
||||
Struct(PP_CollisionData)
|
||||
{
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
PP_EntKey e0;
|
||||
PP_EntKey e1;
|
||||
Vec2 point;
|
||||
Vec2 normal; /* Normal of the collision from e0 to e1 */
|
||||
Vec2 vrel; /* Relative velocity at point of collision */
|
||||
@ -16,24 +16,24 @@ Struct(CollisionData)
|
||||
};
|
||||
|
||||
/* Callback can return 1 to prevent the physics system from resolving */
|
||||
struct SimStepCtx;
|
||||
#define CollisionCallbackFuncDef(name, arg_collision_data, arg_sim_step_ctx) b32 name(CollisionData *arg_collision_data, struct SimStepCtx *arg_sim_step_ctx)
|
||||
typedef CollisionCallbackFuncDef(CollisionCallbackFunc, collision_data, ctx);
|
||||
struct PP_SimStepCtx;
|
||||
#define PP_CollisionCallbackFuncDef(name, arg_collision_data, arg_sim_step_ctx) b32 name(PP_CollisionData *arg_collision_data, struct PP_SimStepCtx *arg_sim_step_ctx)
|
||||
typedef PP_CollisionCallbackFuncDef(PP_CollisionCallbackFunc, collision_data, ctx);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Step ctx
|
||||
|
||||
/* Structure containing data used for a single physics step */
|
||||
Struct(PhysStepCtx)
|
||||
Struct(PP_PhysStepCtx)
|
||||
{
|
||||
struct SimStepCtx *sim_step_ctx;
|
||||
CollisionCallbackFunc *collision_callback;
|
||||
struct PP_SimStepCtx *sim_step_ctx;
|
||||
PP_CollisionCallbackFunc *collision_callback;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Contact types
|
||||
|
||||
Struct(ContactPoint)
|
||||
Struct(PP_ContactPoint)
|
||||
{
|
||||
/* Contact point relative to the center of each entity.
|
||||
*
|
||||
@ -59,13 +59,13 @@ Struct(ContactPoint)
|
||||
#endif
|
||||
};
|
||||
|
||||
Struct(ContactConstraint)
|
||||
Struct(PP_ContactConstraint)
|
||||
{
|
||||
u64 last_phys_iteration; /* To avoid checking collisions for the same constraint twice in one tick */
|
||||
b32 skip_solve;
|
||||
b32 wrong_dir;
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
PP_EntKey e0;
|
||||
PP_EntKey e1;
|
||||
f32 inv_m0;
|
||||
f32 inv_m1;
|
||||
f32 inv_i0;
|
||||
@ -73,7 +73,7 @@ Struct(ContactConstraint)
|
||||
|
||||
Vec2 normal; /* Normal vector of collision from e0 -> e1 */
|
||||
u64 last_iteration;
|
||||
ContactPoint points[2];
|
||||
PP_ContactPoint points[2];
|
||||
u32 num_points;
|
||||
|
||||
f32 friction;
|
||||
@ -81,13 +81,13 @@ Struct(ContactConstraint)
|
||||
f32 pushout_velocity;
|
||||
};
|
||||
|
||||
Struct(ContactDebugData)
|
||||
Struct(PP_ContactDebugData)
|
||||
{
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
PP_EntKey e0;
|
||||
PP_EntKey e1;
|
||||
CLD_CollisionData collision_result;
|
||||
|
||||
ContactPoint points[2];
|
||||
PP_ContactPoint points[2];
|
||||
u32 num_points;
|
||||
|
||||
Vec2 closest0;
|
||||
@ -100,19 +100,19 @@ Struct(ContactDebugData)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Motor joint types
|
||||
|
||||
Struct(MotorJointDesc)
|
||||
Struct(PP_MotorJointDesc)
|
||||
{
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
PP_EntKey e0;
|
||||
PP_EntKey e1;
|
||||
f32 correction_rate;
|
||||
f32 max_force;
|
||||
f32 max_torque;
|
||||
};
|
||||
|
||||
Struct(MotorJoint)
|
||||
Struct(PP_MotorJoint)
|
||||
{
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
PP_EntKey e0;
|
||||
PP_EntKey e1;
|
||||
f32 correction_rate;
|
||||
f32 max_force;
|
||||
f32 max_torque;
|
||||
@ -135,9 +135,9 @@ Struct(MotorJoint)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Mouse joint types
|
||||
|
||||
Struct(MouseJointDesc)
|
||||
Struct(PP_MouseJointDesc)
|
||||
{
|
||||
EntityId target;
|
||||
PP_EntKey target;
|
||||
Vec2 point_local_start;
|
||||
Vec2 point_end;
|
||||
f32 linear_spring_hz;
|
||||
@ -147,9 +147,9 @@ Struct(MouseJointDesc)
|
||||
f32 max_force;
|
||||
};
|
||||
|
||||
Struct(MouseJoint)
|
||||
Struct(PP_MouseJoint)
|
||||
{
|
||||
EntityId target;
|
||||
PP_EntKey target;
|
||||
Vec2 point_local_start;
|
||||
Vec2 point_end;
|
||||
f32 linear_spring_hz;
|
||||
@ -170,10 +170,10 @@ Struct(MouseJoint)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Weld joint types
|
||||
|
||||
Struct(WeldJointDesc)
|
||||
Struct(PP_WeldJointDesc)
|
||||
{
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
PP_EntKey e0;
|
||||
PP_EntKey e1;
|
||||
|
||||
/* The xform that transforms a point in e0's space into the desired e1 space
|
||||
* (IE `xf` * VEC2(0, 0) should evaluate to the local point that e1's origin will lie) */
|
||||
@ -185,10 +185,10 @@ Struct(WeldJointDesc)
|
||||
f32 angular_spring_damp;
|
||||
};
|
||||
|
||||
Struct(WeldJoint)
|
||||
Struct(PP_WeldJoint)
|
||||
{
|
||||
EntityId e0;
|
||||
EntityId e1;
|
||||
PP_EntKey e0;
|
||||
PP_EntKey e1;
|
||||
Xform xf0_to_xf1;
|
||||
|
||||
f32 linear_spring_hz;
|
||||
@ -210,58 +210,57 @@ Struct(WeldJoint)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Contact operations
|
||||
|
||||
b32 CanEntitiesContact(struct Entity *e0, struct Entity *e1);
|
||||
void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteration);
|
||||
void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration);
|
||||
void WarmStartContacts(PhysStepCtx *ctx);
|
||||
void SolveContacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias);
|
||||
b32 PP_CanEntsContact(struct PP_Ent *e0, struct PP_Ent *e1);
|
||||
void PP_CreateAndUpdateContacts(PP_PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteration);
|
||||
void PP_PrepareContacts(PP_PhysStepCtx *ctx, u64 phys_iteration);
|
||||
void PP_WarmStartContacts(PP_PhysStepCtx *ctx);
|
||||
void PP_SolveContacts(PP_PhysStepCtx *ctx, f32 dt, b32 apply_bias);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Motor joint operations
|
||||
|
||||
MotorJointDesc CreateMotorJointDef(void);
|
||||
MotorJoint MotorJointFromDef(MotorJointDesc def);
|
||||
void PrepareMotorJoints(PhysStepCtx *ctx);
|
||||
void WarmStartMotorJoints(PhysStepCtx *ctx);
|
||||
void SolveMotorJoints(PhysStepCtx *ctx, f32 dt);
|
||||
PP_MotorJointDesc PP_CreateMotorJointDef(void);
|
||||
PP_MotorJoint PP_MotorJointFromDef(PP_MotorJointDesc def);
|
||||
void PP_PrepareMotorJoints(PP_PhysStepCtx *ctx);
|
||||
void PP_WarmStartMotorJoints(PP_PhysStepCtx *ctx);
|
||||
void PP_SolveMotorJoints(PP_PhysStepCtx *ctx, f32 dt);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Mouse joint operations
|
||||
|
||||
MouseJointDesc CreateMouseJointDef(void);
|
||||
MouseJoint MouseJointFromDef(MouseJointDesc def);
|
||||
void PrepareMouseJoints(PhysStepCtx *ctx);
|
||||
void WarmStartMouseJoints(PhysStepCtx *ctx);
|
||||
void SolveMouseJoints(PhysStepCtx *ctx, f32 dt);
|
||||
PP_MouseJointDesc PP_CreateMouseJointDef(void);
|
||||
PP_MouseJoint PP_MouseJointFromDef(PP_MouseJointDesc def);
|
||||
void PP_PrepareMouseJoints(PP_PhysStepCtx *ctx);
|
||||
void PP_WarmStartMouseJoints(PP_PhysStepCtx *ctx);
|
||||
void PP_SolveMouseJoints(PP_PhysStepCtx *ctx, f32 dt);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Weld joint operations
|
||||
|
||||
WeldJointDesc CreateWeldJointDef(void);
|
||||
WeldJoint WeldJointFromDef(WeldJointDesc def);
|
||||
void PrepareWeldJoints(PhysStepCtx *ctx);
|
||||
void WarmStartWeldJoints(PhysStepCtx *ctx);
|
||||
void SolveWeldJoints(PhysStepCtx *ctx, f32 dt);
|
||||
PP_WeldJointDesc PP_CreateWeldJointDef(void);
|
||||
PP_WeldJoint PP_WeldJointFromDef(PP_WeldJointDesc def);
|
||||
void PP_PrepareWeldJoints(PP_PhysStepCtx *ctx);
|
||||
void PP_WarmStartWeldJoints(PP_PhysStepCtx *ctx);
|
||||
void PP_SolveWeldJoints(PP_PhysStepCtx *ctx, f32 dt);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Integration operations
|
||||
|
||||
struct Entity;
|
||||
Xform GetDerivedEntityXform(struct Entity *ent, f32 dt);
|
||||
void IntegrateForces(PhysStepCtx *ctx, f32 dt);
|
||||
void IntegrateVelocities(PhysStepCtx *ctx, f32 dt);
|
||||
Xform PP_GetDerivedEntXform(struct PP_Ent *ent, f32 dt);
|
||||
void PP_IntegrateForces(PP_PhysStepCtx *ctx, f32 dt);
|
||||
void PP_IntegrateVelocities(PP_PhysStepCtx *ctx, f32 dt);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Time of impact operations
|
||||
|
||||
f32 DetermineEarliestToi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations);
|
||||
f32 PP_DetermineEarliestToi(PP_PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Spatial operations
|
||||
|
||||
void UpdateAabbs(PhysStepCtx *ctx);
|
||||
void PP_UpdateAabbs(PP_PhysStepCtx *ctx);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Step
|
||||
|
||||
void StepPhys(PhysStepCtx *ctx, f32 timestep);
|
||||
void PP_StepPhys(PP_PhysStepCtx *ctx, f32 timestep);
|
||||
|
||||
350
src/pp/pp_sim.c
350
src/pp/pp_sim.c
@ -1,6 +1,6 @@
|
||||
/* Sim hierarchy is as follows:
|
||||
*
|
||||
* Client store -> clients -> snapshots -> ents
|
||||
* PP_Client store -> clients -> snapshots -> ents
|
||||
*
|
||||
* A client store holds clients, which can be retrieved by client handle or by a host channel id (if one is assigned).
|
||||
*
|
||||
@ -27,37 +27,37 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Startup
|
||||
|
||||
SharedSimCtx shared_sim_ctx = ZI;
|
||||
Readonly ClientStore **_g_sim_client_store_nil = &shared_sim_ctx.nil_client_store;
|
||||
Readonly Client **_g_sim_client_nil = &shared_sim_ctx.nil_client;
|
||||
Readonly Snapshot **_g_sim_snapshot_nil = &shared_sim_ctx.nil_snapshot;
|
||||
Readonly Entity **_g_sim_ent_nil = &shared_sim_ctx.nil_ent;
|
||||
PP_SharedSimCtx PP_shared_sim_ctx = ZI;
|
||||
Readonly PP_ClientStore **PP_nil_client_store = &PP_shared_sim_ctx.nil_client_store;
|
||||
Readonly PP_Client **PP_nil_client = &PP_shared_sim_ctx.nil_client;
|
||||
Readonly PP_Snapshot **PP_nil_snapshot = &PP_shared_sim_ctx.nil_snapshot;
|
||||
Readonly PP_Ent **PP_nil_ent = &PP_shared_sim_ctx.nil_ent;
|
||||
|
||||
void StartupSim(void)
|
||||
void PP_StartupSim(void)
|
||||
{
|
||||
__prof;
|
||||
SharedSimCtx *g = &shared_sim_ctx;
|
||||
PP_SharedSimCtx *g = &PP_shared_sim_ctx;
|
||||
g->nil_arena = AcquireArena(Gibi(1));
|
||||
|
||||
/* Nil client store */
|
||||
g->nil_client_store = PushStruct(g->nil_arena, ClientStore);
|
||||
g->nil_client_store = PushStruct(g->nil_arena, PP_ClientStore);
|
||||
g->nil_client_store->valid = 0;
|
||||
|
||||
/* Nil client */
|
||||
g->nil_client = PushStruct(g->nil_arena, Client);
|
||||
g->nil_client = PushStruct(g->nil_arena, PP_Client);
|
||||
g->nil_client->valid = 0;
|
||||
g->nil_client->store = sim_client_store_nil();
|
||||
g->nil_client->store = PP_NilClientStore();
|
||||
|
||||
/* Nil snapshot */
|
||||
g->nil_snapshot = PushStruct(g->nil_arena, Snapshot);
|
||||
g->nil_snapshot = PushStruct(g->nil_arena, PP_Snapshot);
|
||||
g->nil_snapshot->valid = 0;
|
||||
g->nil_snapshot->client = NilClient();
|
||||
g->nil_snapshot->client = PP_NilClient();
|
||||
|
||||
/* Nil ent */
|
||||
g->nil_ent = PushStruct(g->nil_arena, Entity);
|
||||
g->nil_ent->ss = NilSnapshot();
|
||||
g->nil_ent = PushStruct(g->nil_arena, PP_Ent);
|
||||
g->nil_ent->ss = PP_NilSnapshot();
|
||||
g->nil_ent->valid = 0;
|
||||
g->nil_ent->id = NilEntityId;
|
||||
g->nil_ent->id = PP_NilEntKey;
|
||||
g->nil_ent->_local_xform = XformIdentity;
|
||||
g->nil_ent->_xform = XformIdentity;
|
||||
g->nil_ent->_is_xform_dirty = 0;
|
||||
@ -74,32 +74,32 @@ void StartupSim(void)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Acquire client store
|
||||
|
||||
ClientStore *AcquireClientStore(void)
|
||||
PP_ClientStore *PP_AcquireClientStore(void)
|
||||
{
|
||||
__prof;
|
||||
ClientStore *store;
|
||||
PP_ClientStore *store;
|
||||
{
|
||||
Arena *arena = AcquireArena(Gibi(64));
|
||||
store = PushStruct(arena, ClientStore);
|
||||
store = PushStruct(arena, PP_ClientStore);
|
||||
store->arena = arena;
|
||||
}
|
||||
store->valid = 1;
|
||||
store->num_client_lookup_bins = ClientLookupBinsCount;
|
||||
store->client_lookup_bins = PushStructs(store->arena, ClientLookupBin, store->num_client_lookup_bins);
|
||||
store->num_client_lookup_bins = PP_ClientLookupBinsCount;
|
||||
store->client_lookup_bins = PushStructs(store->arena, PP_ClientLookupBin, store->num_client_lookup_bins);
|
||||
store->clients_arena = AcquireArena(Gibi(64));
|
||||
store->clients = PushDry(store->clients_arena, Client);
|
||||
store->clients = PushDry(store->clients_arena, PP_Client);
|
||||
return store;
|
||||
}
|
||||
|
||||
void ReleaseClientStore(ClientStore *store)
|
||||
void PP_ReleaseClientStore(PP_ClientStore *store)
|
||||
{
|
||||
__prof;
|
||||
for (u64 i = 0; i < store->num_clients_reserved; ++i)
|
||||
{
|
||||
Client *client = &store->clients[i];
|
||||
PP_Client *client = &store->clients[i];
|
||||
if (client->valid)
|
||||
{
|
||||
ReleaseClient(client);
|
||||
PP_ReleaseClient(client);
|
||||
}
|
||||
}
|
||||
ReleaseArena(store->clients_arena);
|
||||
@ -109,10 +109,10 @@ void ReleaseClientStore(ClientStore *store)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Acquire client
|
||||
|
||||
Client *AcquireClient(ClientStore *store)
|
||||
PP_Client *PP_AcquireClient(PP_ClientStore *store)
|
||||
{
|
||||
ClientHandle handle = ZI;
|
||||
Client *client = ClientFromHandle(store, store->first_free_client);
|
||||
PP_ClientKey handle = ZI;
|
||||
PP_Client *client = PP_ClientFromKey(store, store->first_free_client);
|
||||
|
||||
if (client->valid)
|
||||
{
|
||||
@ -122,34 +122,34 @@ Client *AcquireClient(ClientStore *store)
|
||||
}
|
||||
else
|
||||
{
|
||||
client = PushStructNoZero(store->clients_arena, Client);
|
||||
client = PushStructNoZero(store->clients_arena, PP_Client);
|
||||
handle.gen = 1;
|
||||
handle.idx = store->num_clients_reserved;
|
||||
++store->num_clients_reserved;
|
||||
}
|
||||
++store->num_clients_allocated;
|
||||
*client = *NilClient();
|
||||
*client = *PP_NilClient();
|
||||
client->store = store;
|
||||
client->valid = 1;
|
||||
client->handle = handle;
|
||||
|
||||
client->snapshots_arena = AcquireArena(Gibi(8));
|
||||
client->num_snapshot_lookup_bins = TickLookupBinsCount;
|
||||
client->snapshot_lookup_bins = PushStructs(client->snapshots_arena, SnapshotLookupBin, client->num_snapshot_lookup_bins);
|
||||
client->num_snapshot_lookup_bins = PP_TickLookupBinsCount;
|
||||
client->snapshot_lookup_bins = PushStructs(client->snapshots_arena, PP_SnapshotLookupBin, client->num_snapshot_lookup_bins);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
void ReleaseClient(Client *client)
|
||||
void PP_ReleaseClient(PP_Client *client)
|
||||
{
|
||||
/* Release internal snapshot memory */
|
||||
for (u64 i = 0; i < client->num_snapshot_lookup_bins; ++i)
|
||||
{
|
||||
SnapshotLookupBin *bin = &client->snapshot_lookup_bins[i];
|
||||
Snapshot *ss = bin->first;
|
||||
PP_SnapshotLookupBin *bin = &client->snapshot_lookup_bins[i];
|
||||
PP_Snapshot *ss = bin->first;
|
||||
while (ss)
|
||||
{
|
||||
Snapshot *next = ss->next_in_bin;
|
||||
PP_Snapshot *next = ss->next_in_bin;
|
||||
ReleaseArena(ss->ents_arena);
|
||||
ReleaseArena(ss->arena);
|
||||
ss = next;
|
||||
@ -157,10 +157,10 @@ void ReleaseClient(Client *client)
|
||||
}
|
||||
|
||||
/* Remove from channel lookup */
|
||||
SetClientChannelId(client, N_NilChannelId);
|
||||
PP_SetClientChannelId(client, N_NilChannelId);
|
||||
|
||||
/* Release client */
|
||||
ClientStore *store = client->store;
|
||||
PP_ClientStore *store = client->store;
|
||||
client->valid = 0;
|
||||
client->next_free = store->first_free_client;
|
||||
store->first_free_client = client->handle;
|
||||
@ -172,23 +172,23 @@ void ReleaseClient(Client *client)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Client lookup
|
||||
|
||||
u64 ClientChannelHashFromChannelId(N_ChannelId channel_id)
|
||||
u64 PP_ClientChannelHashFromChannelId(N_ChannelId channel_id)
|
||||
{
|
||||
return HashFnv64(Fnv64Basis, StringFromStruct(&channel_id));
|
||||
}
|
||||
|
||||
void SetClientChannelId(Client *client, N_ChannelId channel_id)
|
||||
void PP_SetClientChannelId(PP_Client *client, N_ChannelId channel_id)
|
||||
{
|
||||
ClientStore *store = client->store;
|
||||
PP_ClientStore *store = client->store;
|
||||
N_ChannelId old_channel_id = client->channel_id;
|
||||
|
||||
/* Remove old channel id from channel lookup */
|
||||
if (!N_IsChannelIdNil(old_channel_id))
|
||||
{
|
||||
u64 bin_index = client->channel_hash % store->num_client_lookup_bins;
|
||||
ClientLookupBin *bin = &store->client_lookup_bins[bin_index];
|
||||
Client *prev = ClientFromHandle(store, client->prev_in_bin);
|
||||
Client *next = ClientFromHandle(store, client->next_in_bin);
|
||||
PP_ClientLookupBin *bin = &store->client_lookup_bins[bin_index];
|
||||
PP_Client *prev = PP_ClientFromKey(store, client->prev_in_bin);
|
||||
PP_Client *next = PP_ClientFromKey(store, client->next_in_bin);
|
||||
if (prev->valid)
|
||||
{
|
||||
prev->next_in_bin = next->handle;
|
||||
@ -209,15 +209,15 @@ void SetClientChannelId(Client *client, N_ChannelId channel_id)
|
||||
|
||||
/* Insert into channel lookup */
|
||||
/* TODO: Enforce no duplicates */
|
||||
u64 channel_hash = ClientChannelHashFromChannelId(channel_id);
|
||||
u64 channel_hash = PP_ClientChannelHashFromChannelId(channel_id);
|
||||
client->channel_id = channel_id;
|
||||
client->channel_hash = channel_hash;
|
||||
if (!N_IsChannelIdNil(channel_id))
|
||||
{
|
||||
u64 bin_index = channel_hash % store->num_client_lookup_bins;
|
||||
ClientLookupBin *bin = &store->client_lookup_bins[bin_index];
|
||||
PP_ClientLookupBin *bin = &store->client_lookup_bins[bin_index];
|
||||
{
|
||||
Client *prev_in_bin = ClientFromHandle(store, bin->last);
|
||||
PP_Client *prev_in_bin = PP_ClientFromKey(store, bin->last);
|
||||
if (prev_in_bin->valid)
|
||||
{
|
||||
prev_in_bin->next_in_bin = client->handle;
|
||||
@ -232,13 +232,13 @@ void SetClientChannelId(Client *client, N_ChannelId channel_id)
|
||||
}
|
||||
}
|
||||
|
||||
Client *ClientFromChannelId(ClientStore *store, N_ChannelId channel_id)
|
||||
PP_Client *PP_ClientFromChannelId(PP_ClientStore *store, N_ChannelId channel_id)
|
||||
{
|
||||
Client *result = NilClient();
|
||||
u64 channel_hash = ClientChannelHashFromChannelId(channel_id);
|
||||
PP_Client *result = PP_NilClient();
|
||||
u64 channel_hash = PP_ClientChannelHashFromChannelId(channel_id);
|
||||
u64 bin_index = channel_hash % store->num_client_lookup_bins;
|
||||
ClientLookupBin *bin = &store->client_lookup_bins[bin_index];
|
||||
for (Client *client = ClientFromHandle(store, bin->first); client->valid; client = ClientFromHandle(store, client->next_in_bin))
|
||||
PP_ClientLookupBin *bin = &store->client_lookup_bins[bin_index];
|
||||
for (PP_Client *client = PP_ClientFromKey(store, bin->first); client->valid; client = PP_ClientFromKey(store, client->next_in_bin))
|
||||
{
|
||||
if (client->channel_hash == channel_hash)
|
||||
{
|
||||
@ -249,31 +249,31 @@ Client *ClientFromChannelId(ClientStore *store, N_ChannelId channel_id)
|
||||
return result;
|
||||
}
|
||||
|
||||
Client *ClientFromHandle(ClientStore *store, ClientHandle handle)
|
||||
PP_Client *PP_ClientFromKey(PP_ClientStore *store, PP_ClientKey handle)
|
||||
{
|
||||
if (handle.gen != 0 && handle.idx < store->num_clients_reserved)
|
||||
{
|
||||
Client *client = &store->clients[handle.idx];
|
||||
PP_Client *client = &store->clients[handle.idx];
|
||||
if (client->handle.gen == handle.gen)
|
||||
{
|
||||
return client;
|
||||
}
|
||||
}
|
||||
return NilClient();
|
||||
return PP_NilClient();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Acquire snapshot
|
||||
|
||||
/* Produces a new snapshot at `tick` with data copied from `src` snapshot. */
|
||||
Snapshot *AcquireSnapshot(Client *client, Snapshot *src, u64 tick)
|
||||
PP_Snapshot *PP_AcquireSnapshot(PP_Client *client, PP_Snapshot *src, u64 tick)
|
||||
{
|
||||
if (tick == 0)
|
||||
{
|
||||
return NilSnapshot();
|
||||
return PP_NilSnapshot();
|
||||
}
|
||||
|
||||
Snapshot *ss;
|
||||
PP_Snapshot *ss;
|
||||
{
|
||||
Arena *arena = ZI;
|
||||
Arena *ents_arena = 0;
|
||||
@ -294,7 +294,7 @@ Snapshot *AcquireSnapshot(Client *client, Snapshot *src, u64 tick)
|
||||
}
|
||||
}
|
||||
ResetArena(arena);
|
||||
ss = PushStruct(arena, Snapshot);
|
||||
ss = PushStruct(arena, PP_Snapshot);
|
||||
ss->arena = arena;
|
||||
|
||||
ss->ents_arena = ents_arena;
|
||||
@ -314,8 +314,8 @@ Snapshot *AcquireSnapshot(Client *client, Snapshot *src, u64 tick)
|
||||
ss->phys_iteration = src->phys_iteration;
|
||||
|
||||
/* Copy id lookup bins */
|
||||
ss->num_id_bins = src->num_id_bins > 0 ? src->num_id_bins : IdLookupBinsCount;
|
||||
ss->id_bins = PushStructsNoZero(ss->arena, EntBin, ss->num_id_bins);
|
||||
ss->num_id_bins = src->num_id_bins > 0 ? src->num_id_bins : PP_IdLookupBinsCount;
|
||||
ss->id_bins = PushStructsNoZero(ss->arena, PP_EntBin, ss->num_id_bins);
|
||||
if (src->num_id_bins > 0)
|
||||
{
|
||||
for (u64 i = 0; i < src->num_id_bins; ++i)
|
||||
@ -332,28 +332,28 @@ Snapshot *AcquireSnapshot(Client *client, Snapshot *src, u64 tick)
|
||||
ss->first_free_ent = src->first_free_ent;
|
||||
ss->num_ents_allocated = src->num_ents_allocated;
|
||||
ss->num_ents_reserved = src->num_ents_reserved;
|
||||
ss->ents = PushStructsNoZero(ss->ents_arena, Entity, ss->num_ents_reserved);
|
||||
ss->ents = PushStructsNoZero(ss->ents_arena, PP_Ent, ss->num_ents_reserved);
|
||||
if (ss->num_ents_reserved == 0)
|
||||
{
|
||||
/* Copying from nil snapshot, need to create blank & root entity */
|
||||
|
||||
/* Push blank ent at index 0 (because index 0 is never valid anyway since it maps to NilEntity()) */
|
||||
/* Push blank ent at index 0 (because index 0 is never valid anyway since it maps to nil ent) */
|
||||
{
|
||||
PushStruct(ss->ents_arena, Entity);
|
||||
PushStruct(ss->ents_arena, PP_Ent);
|
||||
++ss->num_ents_allocated;
|
||||
++ss->num_ents_reserved;
|
||||
}
|
||||
|
||||
/* Push root ent with constant id */
|
||||
{
|
||||
Entity *root = PushStructNoZero(ss->ents_arena, Entity);
|
||||
*root = *NilEntity();
|
||||
PP_Ent *root = PushStructNoZero(ss->ents_arena, PP_Ent);
|
||||
*root = *PP_NilEnt();
|
||||
root->ss = ss;
|
||||
root->valid = 1;
|
||||
root->is_root = 1;
|
||||
root->mass_unscaled = F32Infinity;
|
||||
root->inertia_unscaled = F32Infinity;
|
||||
SetEntityId(root, RootEntityId);
|
||||
PP_SetEntKey(root, PP_RootEntKey);
|
||||
++ss->num_ents_allocated;
|
||||
++ss->num_ents_reserved;
|
||||
}
|
||||
@ -362,8 +362,8 @@ Snapshot *AcquireSnapshot(Client *client, Snapshot *src, u64 tick)
|
||||
{
|
||||
for (u64 i = 0; i < ss->num_ents_reserved; ++i)
|
||||
{
|
||||
Entity *dst_ent = &ss->ents[i];
|
||||
Entity *src_ent = &src->ents[i];
|
||||
PP_Ent *dst_ent = &ss->ents[i];
|
||||
PP_Ent *src_ent = &src->ents[i];
|
||||
*dst_ent = *src_ent;
|
||||
dst_ent->ss = ss;
|
||||
}
|
||||
@ -371,27 +371,27 @@ Snapshot *AcquireSnapshot(Client *client, Snapshot *src, u64 tick)
|
||||
|
||||
/* Release duplicate tick if it exists */
|
||||
{
|
||||
Snapshot *existing = SnapshotFromTick(client, tick);
|
||||
PP_Snapshot *existing = PP_SnapshotFromTick(client, tick);
|
||||
if (existing->valid)
|
||||
{
|
||||
ReleaseSnapshot(existing);
|
||||
PP_ReleaseSnapshot(existing);
|
||||
}
|
||||
}
|
||||
|
||||
/* Linear search to insert snapshot in tick order */
|
||||
{
|
||||
Snapshot *prev = SnapshotFromTick(client, client->last_tick);
|
||||
PP_Snapshot *prev = PP_SnapshotFromTick(client, client->last_tick);
|
||||
while (prev->valid)
|
||||
{
|
||||
if (prev->tick < tick)
|
||||
{
|
||||
break;
|
||||
}
|
||||
prev = SnapshotFromTick(client, prev->prev_tick);
|
||||
prev = PP_SnapshotFromTick(client, prev->prev_tick);
|
||||
}
|
||||
if (prev->valid)
|
||||
{
|
||||
Snapshot *next = SnapshotFromTick(client, prev->next_tick);
|
||||
PP_Snapshot *next = PP_SnapshotFromTick(client, prev->next_tick);
|
||||
if (next->valid)
|
||||
{
|
||||
next->prev_tick = tick;
|
||||
@ -406,7 +406,7 @@ Snapshot *AcquireSnapshot(Client *client, Snapshot *src, u64 tick)
|
||||
}
|
||||
else
|
||||
{
|
||||
Snapshot *first = SnapshotFromTick(client, client->first_tick);
|
||||
PP_Snapshot *first = PP_SnapshotFromTick(client, client->first_tick);
|
||||
if (first->valid)
|
||||
{
|
||||
ss->next_tick = first->tick;
|
||||
@ -424,7 +424,7 @@ Snapshot *AcquireSnapshot(Client *client, Snapshot *src, u64 tick)
|
||||
/* Insert into lookup */
|
||||
{
|
||||
u64 bin_index = tick % client->num_snapshot_lookup_bins;
|
||||
SnapshotLookupBin *bin = &client->snapshot_lookup_bins[bin_index];
|
||||
PP_SnapshotLookupBin *bin = &client->snapshot_lookup_bins[bin_index];
|
||||
if (bin->last)
|
||||
{
|
||||
bin->last->next_in_bin = ss;
|
||||
@ -440,16 +440,16 @@ Snapshot *AcquireSnapshot(Client *client, Snapshot *src, u64 tick)
|
||||
return ss;
|
||||
}
|
||||
|
||||
void ReleaseSnapshot(Snapshot *ss)
|
||||
void PP_ReleaseSnapshot(PP_Snapshot *ss)
|
||||
{
|
||||
Client *client = ss->client;
|
||||
PP_Client *client = ss->client;
|
||||
|
||||
/* Remove from lookup */
|
||||
{
|
||||
u64 bin_index = ss->tick % client->num_snapshot_lookup_bins;
|
||||
SnapshotLookupBin *bin = &client->snapshot_lookup_bins[bin_index];
|
||||
Snapshot *prev = ss->prev_in_bin;
|
||||
Snapshot *next = ss->next_in_bin;
|
||||
PP_SnapshotLookupBin *bin = &client->snapshot_lookup_bins[bin_index];
|
||||
PP_Snapshot *prev = ss->prev_in_bin;
|
||||
PP_Snapshot *next = ss->next_in_bin;
|
||||
if (prev)
|
||||
{
|
||||
prev->next_in_bin = next;
|
||||
@ -470,8 +470,8 @@ void ReleaseSnapshot(Snapshot *ss)
|
||||
|
||||
/* Remove from snapshot list */
|
||||
{
|
||||
Snapshot *prev = SnapshotFromTick(client, ss->prev_tick);
|
||||
Snapshot *next = SnapshotFromTick(client, ss->next_tick);
|
||||
PP_Snapshot *prev = PP_SnapshotFromTick(client, ss->prev_tick);
|
||||
PP_Snapshot *next = PP_SnapshotFromTick(client, ss->next_tick);
|
||||
if (prev->valid)
|
||||
{
|
||||
prev->next_tick = next->tick;
|
||||
@ -497,7 +497,7 @@ void ReleaseSnapshot(Snapshot *ss)
|
||||
}
|
||||
|
||||
/* Release all snapshots for client with tick in range [start, end] */
|
||||
void ReleaseSnapshotsInRange(Client *client, u64 start, u64 end)
|
||||
void PP_ReleaseSnapshotsInRange(PP_Client *client, u64 start, u64 end)
|
||||
{
|
||||
if (start > end)
|
||||
{
|
||||
@ -506,7 +506,7 @@ void ReleaseSnapshotsInRange(Client *client, u64 start, u64 end)
|
||||
end = swp;
|
||||
}
|
||||
|
||||
Snapshot *ss = SnapshotFromTick(client, client->first_tick);
|
||||
PP_Snapshot *ss = PP_SnapshotFromTick(client, client->first_tick);
|
||||
while (ss->valid)
|
||||
{
|
||||
u64 tick = ss->tick;
|
||||
@ -515,28 +515,28 @@ void ReleaseSnapshotsInRange(Client *client, u64 start, u64 end)
|
||||
{
|
||||
if (tick <= end)
|
||||
{
|
||||
ReleaseSnapshot(ss);
|
||||
PP_ReleaseSnapshot(ss);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
ss = SnapshotFromTick(client, next_tick);
|
||||
ss = PP_SnapshotFromTick(client, next_tick);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Snapshot lookup
|
||||
|
||||
Snapshot *SnapshotFromTick(Client *client, u64 tick)
|
||||
PP_Snapshot *PP_SnapshotFromTick(PP_Client *client, u64 tick)
|
||||
{
|
||||
Snapshot *ss = NilSnapshot();
|
||||
PP_Snapshot *ss = PP_NilSnapshot();
|
||||
if (tick > 0)
|
||||
{
|
||||
u64 bin_index = tick % client->num_snapshot_lookup_bins;
|
||||
SnapshotLookupBin *bin = &client->snapshot_lookup_bins[bin_index];
|
||||
for (Snapshot *search = bin->first; search; search = search->next_in_bin)
|
||||
PP_SnapshotLookupBin *bin = &client->snapshot_lookup_bins[bin_index];
|
||||
for (PP_Snapshot *search = bin->first; search; search = search->next_in_bin)
|
||||
{
|
||||
if (search->tick == tick)
|
||||
{
|
||||
@ -549,40 +549,40 @@ Snapshot *SnapshotFromTick(Client *client, u64 tick)
|
||||
}
|
||||
|
||||
/* Returns the snapshot at nearest valid tick <= supplied tick */
|
||||
Snapshot *SnapshotFromClosestTickLte(Client *client, u64 tick)
|
||||
PP_Snapshot *PP_SnapshotFromClosestTickLte(PP_Client *client, u64 tick)
|
||||
{
|
||||
Snapshot *ss = SnapshotFromTick(client, tick);
|
||||
PP_Snapshot *ss = PP_SnapshotFromTick(client, tick);
|
||||
if (!ss->valid)
|
||||
{
|
||||
/* Degenerate to linear search */
|
||||
ss = SnapshotFromTick(client, client->last_tick);
|
||||
ss = PP_SnapshotFromTick(client, client->last_tick);
|
||||
while (ss->valid)
|
||||
{
|
||||
if (ss->tick <= tick)
|
||||
{
|
||||
break;
|
||||
}
|
||||
ss = SnapshotFromTick(client, ss->prev_tick);
|
||||
ss = PP_SnapshotFromTick(client, ss->prev_tick);
|
||||
}
|
||||
}
|
||||
return ss;
|
||||
}
|
||||
|
||||
/* Returns the snapshot at nearest valid tick >= supplied tick */
|
||||
Snapshot *SnapshotFromClosestTickGte(Client *client, u64 tick)
|
||||
PP_Snapshot *PP_SnapshotFromClosestTickGte(PP_Client *client, u64 tick)
|
||||
{
|
||||
Snapshot *ss = SnapshotFromTick(client, tick);
|
||||
PP_Snapshot *ss = PP_SnapshotFromTick(client, tick);
|
||||
if (!ss->valid)
|
||||
{
|
||||
/* Degenerate to linear search */
|
||||
ss = SnapshotFromTick(client, client->first_tick);
|
||||
ss = PP_SnapshotFromTick(client, client->first_tick);
|
||||
while (ss->valid)
|
||||
{
|
||||
if (ss->tick >= tick)
|
||||
{
|
||||
break;
|
||||
}
|
||||
ss = SnapshotFromTick(client, ss->next_tick);
|
||||
ss = PP_SnapshotFromTick(client, ss->next_tick);
|
||||
}
|
||||
}
|
||||
return ss;
|
||||
@ -591,7 +591,7 @@ Snapshot *SnapshotFromClosestTickGte(Client *client, u64 tick)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Tile
|
||||
|
||||
Vec2I32 WorldTileIndexFromPos(Vec2 pos)
|
||||
Vec2I32 PP_WorldTileIndexFromPos(Vec2 pos)
|
||||
{
|
||||
Vec2I32 result = VEC2I32(pos.x * SIM_TILES_PER_UNIT_SQRT, pos.y * SIM_TILES_PER_UNIT_SQRT);
|
||||
result.x -= pos.x < 0;
|
||||
@ -599,7 +599,7 @@ Vec2I32 WorldTileIndexFromPos(Vec2 pos)
|
||||
return result;
|
||||
}
|
||||
|
||||
Vec2 PosFromWorldTileIndex(Vec2I32 world_tile_index)
|
||||
Vec2 PP_PosFromWorldTileIndex(Vec2I32 world_tile_index)
|
||||
{
|
||||
Vec2 result = ZI;
|
||||
f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT;
|
||||
@ -608,7 +608,7 @@ Vec2 PosFromWorldTileIndex(Vec2I32 world_tile_index)
|
||||
return result;
|
||||
}
|
||||
|
||||
Vec2I32 LocalTileIndexFromWorldTileIndex(Vec2I32 world_tile_index)
|
||||
Vec2I32 PP_LocalTileIndexFromWorldTileIndex(Vec2I32 world_tile_index)
|
||||
{
|
||||
Vec2I32 result = world_tile_index;
|
||||
result.x += result.x < 0;
|
||||
@ -620,7 +620,7 @@ Vec2I32 LocalTileIndexFromWorldTileIndex(Vec2I32 world_tile_index)
|
||||
return result;
|
||||
}
|
||||
|
||||
Vec2I32 WorldTileIndexFromLocalTileIndex(Vec2I32 tile_chunk_index, Vec2I32 local_tile_index)
|
||||
Vec2I32 PP_WorldTileIndexFromLocalTileIndex(Vec2I32 tile_chunk_index, Vec2I32 local_tile_index)
|
||||
{
|
||||
Vec2I32 result = ZI;
|
||||
result.x = (tile_chunk_index.x * SIM_TILES_PER_CHUNK_SQRT) + local_tile_index.x;
|
||||
@ -628,7 +628,7 @@ Vec2I32 WorldTileIndexFromLocalTileIndex(Vec2I32 tile_chunk_index, Vec2I32 local
|
||||
return result;
|
||||
}
|
||||
|
||||
Vec2I32 TileChunkIndexFromWorldTileIndex(Vec2I32 world_tile_index)
|
||||
Vec2I32 PP_TileChunkIndexFromWorldTileIndex(Vec2I32 world_tile_index)
|
||||
{
|
||||
Vec2I32 result = world_tile_index;
|
||||
result.x += result.x < 0;
|
||||
@ -640,48 +640,48 @@ Vec2I32 TileChunkIndexFromWorldTileIndex(Vec2I32 world_tile_index)
|
||||
return result;
|
||||
}
|
||||
|
||||
void SetSnapshotTile(Snapshot *ss, Vec2I32 world_tile_index, TileKind tile_kind)
|
||||
void PP_SetSnapshotTile(PP_Snapshot *ss, Vec2I32 world_tile_index, PP_TileKind tile_kind)
|
||||
{
|
||||
Vec2I32 chunk_index = TileChunkIndexFromWorldTileIndex(world_tile_index);
|
||||
Vec2I32 chunk_index = PP_TileChunkIndexFromWorldTileIndex(world_tile_index);
|
||||
|
||||
EntityId chunk_id = TileChunkIdFromIndex(chunk_index);
|
||||
Entity *chunk_ent = EntityFromId(ss, chunk_id);
|
||||
PP_EntKey chunk_id = PP_TileChunkKeyFromIndex(chunk_index);
|
||||
PP_Ent *chunk_ent = PP_EntFromKey(ss, chunk_id);
|
||||
if (!chunk_ent->valid)
|
||||
{
|
||||
Entity *root = EntityFromId(ss, RootEntityId);
|
||||
chunk_ent = AcquireSyncSrcWithId(root, chunk_id);
|
||||
EnableProp(chunk_ent, Prop_TileChunk);
|
||||
PP_Ent *root = PP_EntFromKey(ss, PP_RootEntKey);
|
||||
chunk_ent = PP_AcquireSyncSrcEntWithKey(root, chunk_id);
|
||||
PP_EnableProp(chunk_ent, PP_Prop_TileChunk);
|
||||
chunk_ent->tile_chunk_index = chunk_index;
|
||||
}
|
||||
|
||||
Vec2I32 local_index = LocalTileIndexFromWorldTileIndex(world_tile_index);
|
||||
Vec2I32 local_index = PP_LocalTileIndexFromWorldTileIndex(world_tile_index);
|
||||
chunk_ent->tile_chunk_tiles[local_index.x + (local_index.y * SIM_TILES_PER_CHUNK_SQRT)] = tile_kind;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Snapshot lerp
|
||||
|
||||
Snapshot *AcquireSnapshotFromLerp(Client *client, Snapshot *ss0, Snapshot *ss1, f64 blend)
|
||||
PP_Snapshot *PP_AcquireSnapshotFromLerp(PP_Client *client, PP_Snapshot *ss0, PP_Snapshot *ss1, f64 blend)
|
||||
{
|
||||
__prof;
|
||||
|
||||
/* New snapshot will be allocated with same tick as ss0 or ss1, so the result should go into a different client */
|
||||
Assert(ss0->client != client && ss1->client != client);
|
||||
|
||||
Snapshot *ss;
|
||||
PP_Snapshot *ss;
|
||||
b32 should_blend = 1;
|
||||
if (ss0->continuity_gen == ss1->continuity_gen && 0 < blend && blend < 1)
|
||||
{
|
||||
ss = AcquireSnapshot(client, ss0, ss0->tick);
|
||||
ss = PP_AcquireSnapshot(client, ss0, ss0->tick);
|
||||
}
|
||||
else if (RoundF64ToI64(blend) <= 0)
|
||||
{
|
||||
ss = AcquireSnapshot(client, ss0, ss0->tick);
|
||||
ss = PP_AcquireSnapshot(client, ss0, ss0->tick);
|
||||
should_blend = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss = AcquireSnapshot(client, ss1, ss1->tick);
|
||||
ss = PP_AcquireSnapshot(client, ss1, ss1->tick);
|
||||
should_blend = 0;
|
||||
}
|
||||
|
||||
@ -704,10 +704,10 @@ Snapshot *AcquireSnapshotFromLerp(Client *client, Snapshot *ss0, Snapshot *ss1,
|
||||
u64 num_entities = MinU64(ss0->num_ents_reserved, ss1->num_ents_reserved);
|
||||
for (u64 i = 0; i < num_entities; ++i)
|
||||
{
|
||||
Entity *e = &ss->ents[i];
|
||||
Entity *e0 = &ss0->ents[i];
|
||||
Entity *e1 = &ss1->ents[i];
|
||||
LerpEntity(e, e0, e1, blend);
|
||||
PP_Ent *e = &ss->ents[i];
|
||||
PP_Ent *e0 = &ss0->ents[i];
|
||||
PP_Ent *e1 = &ss1->ents[i];
|
||||
PP_LerpEnt(e, e0, e1, blend);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -719,7 +719,7 @@ Snapshot *AcquireSnapshotFromLerp(Client *client, Snapshot *ss0, Snapshot *ss1,
|
||||
//~ Snapshot sync
|
||||
|
||||
/* Syncs entity data between snapshots */
|
||||
void SyncSnapshotEntities(Snapshot *local_ss, Snapshot *remote_ss, EntityId remote_player, u32 sync_flags)
|
||||
void PP_SyncSnapshotEnts(PP_Snapshot *local_ss, PP_Snapshot *remote_ss, PP_EntKey remote_player, u32 sync_flags)
|
||||
{
|
||||
__prof;
|
||||
|
||||
@ -728,44 +728,44 @@ void SyncSnapshotEntities(Snapshot *local_ss, Snapshot *remote_ss, EntityId remo
|
||||
* - Determine new UUids for newly created ents
|
||||
*/
|
||||
|
||||
Entity *local_root = EntityFromId(local_ss, RootEntityId);
|
||||
Entity *remote_root = EntityFromId(remote_ss, RootEntityId);
|
||||
PP_Ent *local_root = PP_EntFromKey(local_ss, PP_RootEntKey);
|
||||
PP_Ent *remote_root = PP_EntFromKey(remote_ss, PP_RootEntKey);
|
||||
|
||||
/* Create new ents from remote */
|
||||
for (Entity *remote_top = EntityFromId(remote_ss, remote_root->first); remote_top->valid; remote_top = EntityFromId(remote_ss, remote_top->next))
|
||||
for (PP_Ent *remote_top = PP_EntFromKey(remote_ss, remote_root->first); remote_top->valid; remote_top = PP_EntFromKey(remote_ss, remote_top->next))
|
||||
{
|
||||
CreateMissingEntitiesFromSnapshots(local_root, remote_top, remote_player);
|
||||
PP_CreateMissingEntsFromSnapshots(local_root, remote_top, remote_player);
|
||||
}
|
||||
|
||||
/* Sync ents with remote, skipping index 0 (nil) & index 1 (root) */
|
||||
for (u64 i = 2; i < local_ss->num_ents_reserved; ++i)
|
||||
{
|
||||
Entity *local_ent = &local_ss->ents[i];
|
||||
if (local_ent->valid && HasProp(local_ent, Prop_SyncDst))
|
||||
PP_Ent *local_ent = &local_ss->ents[i];
|
||||
if (local_ent->valid && PP_HasProp(local_ent, PP_Prop_SyncDst))
|
||||
{
|
||||
b32 should_sync = EqId(local_ent->owner, remote_player) || IsNilId(remote_player);
|
||||
if ((sync_flags & SyncFlag_NoSyncPredictables) && EqId(local_ent->predictor, local_ss->local_player))
|
||||
b32 should_sync = PP_EqEntKey(local_ent->owner, remote_player) || PP_IsNilEntKey(remote_player);
|
||||
if ((sync_flags & PP_SyncFlag_NoSyncPredictables) && PP_EqEntKey(local_ent->predictor, local_ss->local_player))
|
||||
{
|
||||
should_sync = 0;
|
||||
}
|
||||
if (should_sync)
|
||||
{
|
||||
Entity *remote_ent = EntityFromId(remote_ss, local_ent->id);
|
||||
PP_Ent *remote_ent = PP_EntFromKey(remote_ss, local_ent->id);
|
||||
if (remote_ent->valid)
|
||||
{
|
||||
/* Copy all ent data from remote */
|
||||
SyncEntity(local_ent, remote_ent);
|
||||
PP_SyncEnt(local_ent, remote_ent);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remote ent is no longer valid / networked, release it */
|
||||
EnableProp(local_ent, Prop_Release);
|
||||
DisableProp(local_ent, Prop_SyncDst);
|
||||
PP_EnableProp(local_ent, PP_Prop_Release);
|
||||
PP_DisableProp(local_ent, PP_Prop_SyncDst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ReleaseAllWithProp(local_ss, Prop_Release);
|
||||
PP_ReleaseAllWithProp(local_ss, PP_Prop_Release);
|
||||
}
|
||||
|
||||
|
||||
@ -785,7 +785,7 @@ void SyncSnapshotEntities(Snapshot *local_ss, Snapshot *remote_ss, EntityId remo
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Snapshot encode
|
||||
|
||||
void EncodeSnapshot(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapshot *ss1)
|
||||
void PP_EncodeSnapshot(BB_Writer *bw, PP_Client *receiver, PP_Snapshot *ss0, PP_Snapshot *ss1)
|
||||
{
|
||||
__prof;
|
||||
|
||||
@ -808,11 +808,11 @@ void EncodeSnapshot(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapshot *ss
|
||||
u32 old_last = 0;
|
||||
if (i < ss0->num_id_bins)
|
||||
{
|
||||
EntBin *old_bin = &ss0->id_bins[i];
|
||||
PP_EntBin *old_bin = &ss0->id_bins[i];
|
||||
old_first = old_bin->first;
|
||||
old_last = old_bin->last;
|
||||
}
|
||||
EntBin *bin = &ss1->id_bins[i];
|
||||
PP_EntBin *bin = &ss1->id_bins[i];
|
||||
b32 first_diff = bin->first != old_first;
|
||||
b32 last_diff = bin->last != old_last;
|
||||
if (first_diff || last_diff)
|
||||
@ -847,13 +847,13 @@ void EncodeSnapshot(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapshot *ss
|
||||
|
||||
for (u64 i = 1; i < ss1->num_ents_reserved; ++i)
|
||||
{
|
||||
Entity *e0 = NilEntity();
|
||||
PP_Ent *e0 = PP_NilEnt();
|
||||
if (i < ss0->num_ents_reserved)
|
||||
{
|
||||
e0 = &ss0->ents[i];
|
||||
}
|
||||
Entity *e1 = &ss1->ents[i];
|
||||
EncodeEntity(bw, e0, e1);
|
||||
PP_Ent *e1 = &ss1->ents[i];
|
||||
PP_EncodeEnt(bw, e0, e1);
|
||||
}
|
||||
|
||||
BB_WriteDebugMarker(bw, Lit("SNAPSHOT END"));
|
||||
@ -862,7 +862,7 @@ void EncodeSnapshot(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapshot *ss
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Snapshot decode
|
||||
|
||||
void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
void PP_DecodeSnapshot(BB_Reader *br, PP_Snapshot *ss)
|
||||
{
|
||||
__prof;
|
||||
|
||||
@ -874,7 +874,7 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
ss->continuity_gen = BB_ReadUV(br);
|
||||
ss->phys_iteration = BB_ReadUV(br);
|
||||
|
||||
ss->local_player = (EntityId){ .uid = BB_ReadUid(br) };
|
||||
ss->local_player = (PP_EntKey){ .uid = BB_ReadUid(br) };
|
||||
|
||||
/* Id bins */
|
||||
/* TODO: Don't decode these, determine them implicitly from decoded ents */
|
||||
@ -886,7 +886,7 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
u32 bin_index = BB_ReadUV(br);
|
||||
if (bin_index < ss->num_id_bins)
|
||||
{
|
||||
EntBin *bin = &ss->id_bins[bin_index];
|
||||
PP_EntBin *bin = &ss->id_bins[bin_index];
|
||||
if (BB_ReadBit(br))
|
||||
{
|
||||
bin->first = BB_ReadUV(br);
|
||||
@ -920,11 +920,11 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved;
|
||||
if (reserve_diff > 0)
|
||||
{
|
||||
PushStructsNoZero(ss->ents_arena, Entity, reserve_diff);
|
||||
PushStructsNoZero(ss->ents_arena, PP_Ent, reserve_diff);
|
||||
for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i)
|
||||
{
|
||||
Entity *e = &ss->ents[i];
|
||||
*e = *NilEntity();
|
||||
PP_Ent *e = &ss->ents[i];
|
||||
*e = *PP_NilEnt();
|
||||
e->ss = ss;
|
||||
}
|
||||
}
|
||||
@ -940,9 +940,9 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
BB_ReadDebugMarker(br, StringFromStruct(&ss->num_ents_reserved));
|
||||
for (u64 i = 1; i < ss->num_ents_reserved; ++i)
|
||||
{
|
||||
Entity *e = &ss->ents[i];
|
||||
PP_Ent *e = &ss->ents[i];
|
||||
e->ss = ss;
|
||||
DecodeEntity(br, e);
|
||||
PP_DecodeEnt(br, e);
|
||||
}
|
||||
|
||||
BB_ReadDebugMarker(br, Lit("SNAPSHOT END"));
|
||||
@ -954,7 +954,7 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Snapshot encode
|
||||
|
||||
void EncodeSnapshot(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapshot *ss1)
|
||||
void PP_EncodeSnapshot(BB_Writer *bw, PP_Client *receiver, PP_Snapshot *ss0, PP_Snapshot *ss1)
|
||||
{
|
||||
__prof;
|
||||
|
||||
@ -993,7 +993,7 @@ void EncodeSnapshot(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapshot *ss
|
||||
BB_AlignWriter(bw);
|
||||
for (u64 i = 0; i < ss1->num_ents_reserved; ++i)
|
||||
{
|
||||
Entity *e0 = NilEntity();
|
||||
PP_Ent *e0 = PP_NilEnt();
|
||||
if (i < ss0->num_ents_reserved)
|
||||
{
|
||||
e0 = &ss0->ents[i];
|
||||
@ -1015,8 +1015,8 @@ void EncodeSnapshot(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapshot *ss
|
||||
|
||||
if (e1->valid)
|
||||
{
|
||||
Entity *e1 = &ss1->ents[i];
|
||||
EncodeEntity(bw, e0, e1);
|
||||
PP_Ent *e1 = &ss1->ents[i];
|
||||
PP_EncodeEnt(bw, e0, e1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1035,7 +1035,7 @@ struct sim_ent_decode_queue
|
||||
struct sim_ent_decode_node *last;
|
||||
};
|
||||
|
||||
void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
void PP_DecodeSnapshot(BB_Reader *br, PP_Snapshot *ss)
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
@ -1046,7 +1046,7 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
ss->continuity_gen = BB_ReadUV(br);
|
||||
ss->phys_iteration = BB_ReadUV(br);
|
||||
|
||||
ss->local_player = (EntityId){ .uid = BB_ReadUid(br) };
|
||||
ss->local_player = (PP_EntKey){ .uid = BB_ReadUid(br) };
|
||||
|
||||
#if 1
|
||||
|
||||
@ -1061,11 +1061,11 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved;
|
||||
if (reserve_diff > 0)
|
||||
{
|
||||
PushStructsNoZero(ss->ents_arena, Entity, reserve_diff);
|
||||
PushStructsNoZero(ss->ents_arena, PP_Ent, reserve_diff);
|
||||
for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i)
|
||||
{
|
||||
Entity *e = &ss->ents[i];
|
||||
*e = *NilEntity();
|
||||
PP_Ent *e = &ss->ents[i];
|
||||
*e = *PP_NilEnt();
|
||||
e->ss = ss;
|
||||
}
|
||||
}
|
||||
@ -1082,17 +1082,17 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
b32 released = 0;
|
||||
|
||||
u32 alloc_parent_index = ZI;
|
||||
EntityId alloc_ent_id = ZI;
|
||||
PP_EntKey alloc_ent_id = ZI;
|
||||
if (allocation_changed)
|
||||
{
|
||||
released = BB_ReadBit(br);
|
||||
if (released)
|
||||
{
|
||||
Entity *e = sim_ent_from_index(ss, e);
|
||||
PP_Ent *e = sim_ent_from_index(ss, e);
|
||||
Assert(e->valid); /* An entity that we don't have allocated should never have been marked for release */
|
||||
if (e->valid)
|
||||
{
|
||||
EnableProp(e, Prop_Release);
|
||||
PP_EnableProp(e, PP_Prop_Release);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1135,14 +1135,14 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
if (n->is_new)
|
||||
{
|
||||
u32 index = n->index;
|
||||
Entity *parent = sim_ent_from_index(ss, n->alloc_parent_index);
|
||||
Assert(!sim_ent_from_index(ss, index)->valid && !EntityFromId(ss, alloc_ent_id)->valid); /* An entity that we have allocated already should never be marked for allocation */
|
||||
PP_Ent *parent = sim_ent_from_index(ss, n->alloc_parent_index);
|
||||
Assert(!sim_ent_from_index(ss, index)->valid && !PP_EntFromKey(ss, alloc_ent_id)->valid); /* An entity that we have allocated already should never be marked for allocation */
|
||||
Assert(parent->valid); /* Parent for new entity allocation should always be valid */
|
||||
if (parent->valid && index < ss->num_ents_reserved)
|
||||
{
|
||||
Entity *ent = &ss->ents[index];
|
||||
PP_Ent *ent = &ss->ents[index];
|
||||
ent->valid = 1;
|
||||
SetEntityId(ent, n->alloc_ent_id);
|
||||
PP_SetEntKey(ent, n->alloc_ent_id);
|
||||
Link(parent, ent);
|
||||
}
|
||||
else
|
||||
@ -1158,10 +1158,10 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
{
|
||||
BB_Reader ent_br = n->br;
|
||||
u32 index = n->index;
|
||||
Entity *e = sim_ent_from_index(ss, index);
|
||||
PP_Ent *e = sim_ent_from_index(ss, index);
|
||||
if (e->valid)
|
||||
{
|
||||
DecodeEntity(&ent_br, e);
|
||||
PP_DecodeEnt(&ent_br, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1182,11 +1182,11 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved;
|
||||
if (reserve_diff > 0)
|
||||
{
|
||||
PushStructsNoZero(ss->ents_arena, Entity, reserve_diff);
|
||||
PushStructsNoZero(ss->ents_arena, PP_Ent, reserve_diff);
|
||||
for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i)
|
||||
{
|
||||
Entity *e = &ss->ents[i];
|
||||
*e = *NilEntity();
|
||||
PP_Ent *e = &ss->ents[i];
|
||||
*e = *PP_NilEnt();
|
||||
e->ss = ss;
|
||||
}
|
||||
}
|
||||
@ -1203,14 +1203,14 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
}
|
||||
else
|
||||
{
|
||||
EnableProp(e, Prop_Release);
|
||||
PP_EnableProp(e, PP_Prop_Release);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < ss->num_ents_reserved; ++i)
|
||||
{
|
||||
Entity *e = &ss->ents[i];
|
||||
PP_Ent *e = &ss->ents[i];
|
||||
e->ss = ss;
|
||||
|
||||
b32 valid_changed = BB_ReadBit(br);
|
||||
@ -1226,15 +1226,15 @@ void DecodeSnapshot(BB_Reader *br, Snapshot *ss)
|
||||
Assert(e->valid);
|
||||
if (e->valid)
|
||||
{
|
||||
EnableProp(e, Prop_Release);
|
||||
PP_EnableProp(e, PP_Prop_Release);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DecodeEntity(br, e);
|
||||
PP_DecodeEnt(br, e);
|
||||
}
|
||||
}
|
||||
ReleaseAllWithProp(ss, Prop_Release);
|
||||
PP_ReleaseAllWithProp(ss, PP_Prop_Release);
|
||||
#endif
|
||||
|
||||
EndScratch(scratch);
|
||||
|
||||
234
src/pp/pp_sim.h
234
src/pp/pp_sim.h
@ -1,66 +1,66 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Id types
|
||||
//~ Key types
|
||||
|
||||
Struct(EntityId)
|
||||
Struct(PP_EntKey)
|
||||
{
|
||||
Uid uid;
|
||||
};
|
||||
|
||||
Struct(ClientHandle)
|
||||
Struct(PP_ClientKey)
|
||||
{
|
||||
u32 idx;
|
||||
u32 gen;
|
||||
};
|
||||
|
||||
#define NilClientHandle ((ClientHandle) { .gen = 0, .idx = 0 })
|
||||
#define PP_NilClientHandle ((PP_ClientKey) { .gen = 0, .idx = 0 })
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Client store types
|
||||
|
||||
Struct(ClientLookupBin)
|
||||
Struct(PP_ClientLookupBin)
|
||||
{
|
||||
struct ClientHandle first;
|
||||
struct ClientHandle last;
|
||||
PP_ClientKey first;
|
||||
PP_ClientKey last;
|
||||
};
|
||||
|
||||
Struct(ClientStore)
|
||||
Struct(PP_ClientStore)
|
||||
{
|
||||
b32 valid;
|
||||
Arena *arena;
|
||||
|
||||
/* Client lookup */
|
||||
ClientLookupBin *client_lookup_bins;
|
||||
PP_ClientLookupBin *client_lookup_bins;
|
||||
u64 num_client_lookup_bins;
|
||||
|
||||
/* Clients */
|
||||
Arena *clients_arena;
|
||||
struct Client *clients;
|
||||
ClientHandle first_free_client;
|
||||
struct PP_Client *clients;
|
||||
PP_ClientKey first_free_client;
|
||||
u64 num_clients_allocated;
|
||||
u64 num_clients_reserved;
|
||||
};
|
||||
|
||||
Inline ClientStore *sim_client_store_nil(void)
|
||||
Inline PP_ClientStore *PP_NilClientStore(void)
|
||||
{
|
||||
extern Readonly ClientStore **_g_sim_client_store_nil;
|
||||
return *_g_sim_client_store_nil;
|
||||
extern Readonly PP_ClientStore **PP_nil_client_store;
|
||||
return *PP_nil_client_store;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Client types
|
||||
|
||||
Struct(SnapshotLookupBin)
|
||||
Struct(PP_SnapshotLookupBin)
|
||||
{
|
||||
struct Snapshot *first;
|
||||
struct Snapshot *last;
|
||||
struct PP_Snapshot *first;
|
||||
struct PP_Snapshot *last;
|
||||
};
|
||||
|
||||
Struct(Client)
|
||||
Struct(PP_Client)
|
||||
{
|
||||
b32 valid;
|
||||
ClientHandle handle;
|
||||
ClientStore *store;
|
||||
PP_ClientKey handle;
|
||||
PP_ClientStore *store;
|
||||
|
||||
Arena *snapshots_arena;
|
||||
|
||||
@ -70,12 +70,12 @@ Struct(Client)
|
||||
N_ChannelId channel_id;
|
||||
u64 channel_hash;
|
||||
|
||||
ClientHandle next_free;
|
||||
ClientHandle next_in_bin;
|
||||
ClientHandle prev_in_bin;
|
||||
PP_ClientKey next_free;
|
||||
PP_ClientKey next_in_bin;
|
||||
PP_ClientKey prev_in_bin;
|
||||
|
||||
/* The client's player entity id in the master sim (if relevant) */
|
||||
EntityId player_id;
|
||||
PP_EntKey player_id;
|
||||
|
||||
/* This is the highest confirmed tick of ours that we know this client has received */
|
||||
u64 ack;
|
||||
@ -92,20 +92,20 @@ Struct(Client)
|
||||
u64 first_tick;
|
||||
u64 last_tick;
|
||||
u64 num_ticks;
|
||||
struct Snapshot *first_free_snapshot;
|
||||
struct PP_Snapshot *first_free_snapshot;
|
||||
|
||||
/* Tick -> snapshot lookup */
|
||||
u64 num_snapshot_lookup_bins;
|
||||
SnapshotLookupBin *snapshot_lookup_bins;
|
||||
PP_SnapshotLookupBin *snapshot_lookup_bins;
|
||||
};
|
||||
|
||||
Inline Client *NilClient(void)
|
||||
Inline PP_Client *PP_NilClient(void)
|
||||
{
|
||||
extern Readonly Client **_g_sim_client_nil;
|
||||
return *_g_sim_client_nil;
|
||||
extern Readonly PP_Client **PP_nil_client;
|
||||
return *PP_nil_client;
|
||||
}
|
||||
|
||||
Inline b32 EqClientHandle(ClientHandle a, ClientHandle b)
|
||||
Inline b32 PP_EqClientKey(PP_ClientKey a, PP_ClientKey b)
|
||||
{
|
||||
return a.gen == b.gen && a.idx == b.idx;
|
||||
}
|
||||
@ -114,82 +114,82 @@ Inline b32 EqClientHandle(ClientHandle a, ClientHandle b)
|
||||
//~ Layer types
|
||||
|
||||
/* Absolute layers */
|
||||
#define Layer_FloorDecals (-300)
|
||||
#define Layer_Bullets (-200)
|
||||
#define Layer_Tracers (-100)
|
||||
#define Layer_Shoulders (0)
|
||||
#define Layer_Walls (100)
|
||||
#define PP_Layer_FloorDecals (-300)
|
||||
#define PP_Layer_Bullets (-200)
|
||||
#define PP_Layer_Tracers (-100)
|
||||
#define PP_Layer_Shoulders (0)
|
||||
#define PP_Layer_Walls (100)
|
||||
|
||||
/* Relative layers */
|
||||
#define Layer_DefaultRelative (0)
|
||||
#define Layer_RelativeWeapon (1)
|
||||
#define PP_Layer_DefaultRelative (0)
|
||||
#define PP_Layer_RelativeWeapon (1)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Control types
|
||||
|
||||
Enum(ControlFlag)
|
||||
Enum(PP_ControlFlag)
|
||||
{
|
||||
ControlFlag_Fire = 1 << 0,
|
||||
ControlFlag_AltFire = 1 << 1,
|
||||
PP_ControlFlag_Fire = 1 << 0,
|
||||
PP_ControlFlag_AltFire = 1 << 1,
|
||||
|
||||
/* Testing */
|
||||
ControlFlag_Drag = 1 << 2,
|
||||
ControlFlag_Delete = 1 << 3,
|
||||
ControlFlag_ClearAll = 1 << 4,
|
||||
ControlFlag_SpawnTest1 = 1 << 5,
|
||||
ControlFlag_SpawnTest2 = 1 << 6,
|
||||
ControlFlag_SpawnTest3 = 1 << 7,
|
||||
ControlFlag_SpawnTest4 = 1 << 8,
|
||||
ControlFlag_TestWalls = 1 << 9,
|
||||
ControlFlag_TestTiles = 1 << 10,
|
||||
ControlFlag_TestExplode = 1 << 11,
|
||||
ControlFlag_TestTeleport = 1 << 12,
|
||||
PP_ControlFlag_Drag = 1 << 2,
|
||||
PP_ControlFlag_Delete = 1 << 3,
|
||||
PP_ControlFlag_ClearAll = 1 << 4,
|
||||
PP_ControlFlag_SpawnTest1 = 1 << 5,
|
||||
PP_ControlFlag_SpawnTest2 = 1 << 6,
|
||||
PP_ControlFlag_SpawnTest3 = 1 << 7,
|
||||
PP_ControlFlag_SpawnTest4 = 1 << 8,
|
||||
PP_ControlFlag_TestWalls = 1 << 9,
|
||||
PP_ControlFlag_TestTiles = 1 << 10,
|
||||
PP_ControlFlag_TestExplode = 1 << 11,
|
||||
PP_ControlFlag_TestTeleport = 1 << 12,
|
||||
};
|
||||
|
||||
Struct(ControlData)
|
||||
Struct(PP_ControlData)
|
||||
{
|
||||
Vec2 move; /* Movement direction vector (speed of 0 -> 1) */
|
||||
Vec2 focus; /* Focus direction vector (where does the controller want to look) */
|
||||
Vec2 dbg_cursor; /* Where is the user's cursor in the world (used for things like editing the world) */
|
||||
ControlFlag flags;
|
||||
PP_ControlFlag flags;
|
||||
};
|
||||
|
||||
Enum(CmdKind)
|
||||
Enum(PP_CmdKind)
|
||||
{
|
||||
CmdKind_Invalid,
|
||||
PP_CmdKind_Invalid,
|
||||
|
||||
CmdKind_Control,
|
||||
CmdKind_Chat
|
||||
PP_CmdKind_Control,
|
||||
PP_CmdKind_Chat
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Tile types
|
||||
|
||||
Enum(TileKind)
|
||||
Enum(PP_TileKind)
|
||||
{
|
||||
TileKind_None,
|
||||
TileKind_Wall,
|
||||
PP_TileKind_None,
|
||||
PP_TileKind_Wall,
|
||||
|
||||
TileKind_Count
|
||||
PP_TileKind_Count
|
||||
};
|
||||
StaticAssert(TileKind_Count < 256); /* Tile kind must fit in 8 bits */
|
||||
StaticAssert(PP_TileKind_Count < 256); /* Tile kind must fit in 8 bits */
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Snapshot types
|
||||
|
||||
Enum(SyncFlag)
|
||||
Enum(PP_SyncFlag)
|
||||
{
|
||||
SyncFlag_NoSyncPredictables = 1 << 0
|
||||
PP_SyncFlag_NoSyncPredictables = 1 << 0
|
||||
};
|
||||
|
||||
Struct(Snapshot)
|
||||
Struct(PP_Snapshot)
|
||||
{
|
||||
b32 valid;
|
||||
u64 tick;
|
||||
Client *client;
|
||||
Snapshot *next_free;
|
||||
Snapshot *next_in_bin;
|
||||
Snapshot *prev_in_bin;
|
||||
PP_Client *client;
|
||||
PP_Snapshot *next_free;
|
||||
PP_Snapshot *next_in_bin;
|
||||
PP_Snapshot *prev_in_bin;
|
||||
u64 prev_tick;
|
||||
u64 next_tick;
|
||||
|
||||
@ -206,119 +206,117 @@ Struct(Snapshot)
|
||||
u64 phys_iteration;
|
||||
|
||||
/* The id of the receiver's player in the snapshot */
|
||||
EntityId local_player;
|
||||
PP_EntKey local_player;
|
||||
|
||||
/* Id lookup */
|
||||
struct EntBin *id_bins;
|
||||
struct PP_EntBin *id_bins;
|
||||
u64 num_id_bins;
|
||||
|
||||
/* Entities */
|
||||
/* Ents */
|
||||
Arena *ents_arena;
|
||||
struct Entity *ents;
|
||||
struct PP_Ent *ents;
|
||||
u32 first_free_ent;
|
||||
u32 num_ents_allocated;
|
||||
u32 num_ents_reserved;
|
||||
};
|
||||
|
||||
Inline Snapshot *NilSnapshot(void)
|
||||
Inline PP_Snapshot *PP_NilSnapshot(void)
|
||||
{
|
||||
extern Readonly Snapshot **_g_sim_snapshot_nil;
|
||||
return *_g_sim_snapshot_nil;
|
||||
extern Readonly PP_Snapshot **PP_nil_snapshot;
|
||||
return *PP_nil_snapshot;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ State types
|
||||
|
||||
#define ClientLookupBinsCount 127
|
||||
#define TickLookupBinsCount 127
|
||||
#define IdLookupBinsCount 4096
|
||||
#define PP_ClientLookupBinsCount 127
|
||||
#define PP_TickLookupBinsCount 127
|
||||
#define PP_IdLookupBinsCount 4096
|
||||
|
||||
Struct(SharedSimCtx)
|
||||
Struct(PP_SharedSimCtx)
|
||||
{
|
||||
Arena *nil_arena;
|
||||
ClientStore *nil_client_store;
|
||||
Client *nil_client;
|
||||
Snapshot *nil_snapshot;
|
||||
struct Entity *nil_ent;
|
||||
};
|
||||
PP_ClientStore *nil_client_store;
|
||||
PP_Client *nil_client;
|
||||
PP_Snapshot *nil_snapshot;
|
||||
struct PP_Ent *nil_ent;
|
||||
} extern PP_shared_sim_ctx;
|
||||
|
||||
extern SharedSimCtx shared_sim_ctx;
|
||||
/* Accessed via `PP_NilClientStore()` */
|
||||
extern Readonly PP_ClientStore **PP_nil_client_store;
|
||||
|
||||
/* Accessed via `sim_client_store_nil()` */
|
||||
extern Readonly ClientStore **_g_sim_client_store_nil;
|
||||
|
||||
/* Accessed via `NilClient()` */
|
||||
extern Readonly Client **_g_sim_client_nil;
|
||||
/* Accessed via `PP_NilClient()` */
|
||||
extern Readonly PP_Client **PP_nil_client;
|
||||
|
||||
/* Accessed via `NilSnapshot()` */
|
||||
extern Readonly Snapshot **_g_sim_snapshot_nil;
|
||||
extern Readonly struct Entity **_g_sim_ent_nil;
|
||||
extern Readonly PP_Snapshot **PP_nil_snapshot;
|
||||
extern Readonly struct PP_Ent **PP_nil_ent;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Startup
|
||||
|
||||
void StartupSim(void);
|
||||
void PP_StartupSim(void);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Client store acquire operations
|
||||
|
||||
ClientStore *AcquireClientStore(void);
|
||||
void ReleaseClientStore(ClientStore *store);
|
||||
PP_ClientStore *PP_AcquireClientStore(void);
|
||||
void PP_ReleaseClientStore(PP_ClientStore *store);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Client acquire operations
|
||||
|
||||
Client *AcquireClient(ClientStore *store);
|
||||
void ReleaseClient(Client *client);
|
||||
PP_Client *PP_AcquireClient(PP_ClientStore *store);
|
||||
void PP_ReleaseClient(PP_Client *client);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Client lookup operations
|
||||
|
||||
u64 ClientChannelHashFromChannelId(N_ChannelId channel_id);
|
||||
void SetClientChannelId(Client *client, N_ChannelId channel_id);
|
||||
Client *ClientFromChannelId(ClientStore *store, N_ChannelId channel_id);
|
||||
Client *ClientFromHandle(ClientStore *store, ClientHandle handle);
|
||||
u64 PP_ClientChannelHashFromChannelId(N_ChannelId channel_id);
|
||||
void PP_SetClientChannelId(PP_Client *client, N_ChannelId channel_id);
|
||||
PP_Client *PP_ClientFromChannelId(PP_ClientStore *store, N_ChannelId channel_id);
|
||||
PP_Client *PP_ClientFromKey(PP_ClientStore *store, PP_ClientKey handle);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Snapshot acquire operations
|
||||
|
||||
Snapshot *AcquireSnapshot(Client *client, Snapshot *src, u64 tick);
|
||||
void ReleaseSnapshot(Snapshot *ss);
|
||||
void ReleaseSnapshotsInRange(Client *client, u64 start, u64 end);
|
||||
PP_Snapshot *PP_AcquireSnapshot(PP_Client *client, PP_Snapshot *src, u64 tick);
|
||||
void PP_ReleaseSnapshot(PP_Snapshot *ss);
|
||||
void PP_ReleaseSnapshotsInRange(PP_Client *client, u64 start, u64 end);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Snapshot lookup operations
|
||||
|
||||
Snapshot *SnapshotFromTick(Client *client, u64 tick);
|
||||
Snapshot *SnapshotFromClosestTickLte(Client *client, u64 tick);
|
||||
Snapshot *SnapshotFromClosestTickGte(Client *client, u64 tick);
|
||||
PP_Snapshot *PP_SnapshotFromTick(PP_Client *client, u64 tick);
|
||||
PP_Snapshot *PP_SnapshotFromClosestTickLte(PP_Client *client, u64 tick);
|
||||
PP_Snapshot *PP_SnapshotFromClosestTickGte(PP_Client *client, u64 tick);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Tile operations
|
||||
|
||||
Vec2I32 WorldTileIndexFromPos(Vec2 pos);
|
||||
Vec2 PosFromWorldTileIndex(Vec2I32 world_tile_index);
|
||||
Vec2I32 LocalTileIndexFromWorldTileIndex(Vec2I32 world_tile_index);
|
||||
Vec2I32 WorldTileIndexFromLocalTileIndex(Vec2I32 tile_chunk_index, Vec2I32 local_tile_index);
|
||||
Vec2I32 TileChunkIndexFromWorldTileIndex(Vec2I32 world_tile_index);
|
||||
void SetSnapshotTile(Snapshot *ss, Vec2I32 world_tile_index, TileKind tile_kind);
|
||||
Vec2I32 PP_WorldTileIndexFromPos(Vec2 pos);
|
||||
Vec2 PP_PosFromWorldTileIndex(Vec2I32 world_tile_index);
|
||||
Vec2I32 PP_LocalTileIndexFromWorldTileIndex(Vec2I32 world_tile_index);
|
||||
Vec2I32 PP_WorldTileIndexFromLocalTileIndex(Vec2I32 tile_chunk_index, Vec2I32 local_tile_index);
|
||||
Vec2I32 PP_TileChunkIndexFromWorldTileIndex(Vec2I32 world_tile_index);
|
||||
void PP_SetSnapshotTile(PP_Snapshot *ss, Vec2I32 world_tile_index, PP_TileKind tile_kind);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Snapshot lerp operations
|
||||
|
||||
Snapshot *AcquireSnapshotFromLerp(Client *client, Snapshot *ss0, Snapshot *ss1, f64 blend);
|
||||
PP_Snapshot *PP_AcquireSnapshotFromLerp(PP_Client *client, PP_Snapshot *ss0, PP_Snapshot *ss1, f64 blend);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Snapshot sync operations
|
||||
|
||||
void SyncSnapshotEntities(Snapshot *local_ss, Snapshot *remote_ss, EntityId remote_player, u32 sync_flags);
|
||||
void PP_SyncSnapshotEnts(PP_Snapshot *local_ss, PP_Snapshot *remote_ss, PP_EntKey remote_player, u32 sync_flags);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Snapshot encode operations
|
||||
|
||||
void EncodeSnapshot(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapshot *ss1);
|
||||
void PP_EncodeSnapshot(BB_Writer *bw, PP_Client *receiver, PP_Snapshot *ss0, PP_Snapshot *ss1);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Snapshot decode operations
|
||||
|
||||
void DecodeSnapshot(BB_Reader *br, Snapshot *ss);
|
||||
void PP_DecodeSnapshot(BB_Reader *br, PP_Snapshot *ss);
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
/* FIXME: Default space entry & cell pointers to nil */
|
||||
|
||||
Readonly SpaceEntry _g_space_entry_nil = ZI;
|
||||
Readonly SpaceCell _g_space_cell_nil = ZI;
|
||||
Readonly Space _g_space_nil = ZI;
|
||||
Readonly PP_SpaceEntry PP_nil_space_entry = ZI;
|
||||
Readonly PP_SpaceCell PP_nil_space_cell = ZI;
|
||||
Readonly PP_Space PP_nil_space = ZI;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Space
|
||||
@ -10,63 +10,63 @@ Readonly Space _g_space_nil = ZI;
|
||||
/* NOTE:
|
||||
* The number of bins determines how often tiles will collide in the spatial hash.
|
||||
* For example, at `num_bins_sqrt` = 256 (65536 bins), tiles <1, 1>, <1, 257>, and <257, 257> will collide. */
|
||||
Space *AcquireSpace(f32 cell_size, u32 num_bins_sqrt)
|
||||
PP_Space *PP_AcquireSpace(f32 cell_size, u32 num_bins_sqrt)
|
||||
{
|
||||
Space *space;
|
||||
PP_Space *space;
|
||||
{
|
||||
Arena *arena = AcquireArena(Gibi(64));
|
||||
space = PushStruct(arena, Space);
|
||||
space = PushStruct(arena, PP_Space);
|
||||
space->entry_arena = arena;
|
||||
}
|
||||
|
||||
space->valid = 1;
|
||||
space->entries = PushDry(space->entry_arena, SpaceEntry);
|
||||
space->entries = PushDry(space->entry_arena, PP_SpaceEntry);
|
||||
|
||||
space->cell_arena = AcquireArena(Gibi(64));
|
||||
space->cell_size = cell_size;
|
||||
space->num_bins = num_bins_sqrt * num_bins_sqrt;
|
||||
space->num_bins_sqrt = num_bins_sqrt;
|
||||
space->bins = PushStructs(space->cell_arena, SpaceCellBin, space->num_bins);
|
||||
space->bins = PushStructs(space->cell_arena, PP_SpaceCellBin, space->num_bins);
|
||||
|
||||
return space;
|
||||
}
|
||||
|
||||
void ReleaseSpace(Space *space)
|
||||
void PP_ReleaseSpace(PP_Space *space)
|
||||
{
|
||||
ReleaseArena(space->cell_arena);
|
||||
ReleaseArena(space->entry_arena);
|
||||
}
|
||||
|
||||
void ResetSpace(Space *space)
|
||||
void PP_ResetSpace(PP_Space *space)
|
||||
{
|
||||
PopTo(space->entry_arena, (u64)space->entries - (u64)ArenaBase(space->entry_arena));
|
||||
ResetArena(space->cell_arena);
|
||||
space->bins = PushStructs(space->cell_arena, SpaceCellBin, space->num_bins);
|
||||
space->bins = PushStructs(space->cell_arena, PP_SpaceCellBin, space->num_bins);
|
||||
space->num_entries_reserved = 0;
|
||||
space->first_free_cell = 0;
|
||||
space->first_free_cell_node = 0;
|
||||
space->first_free_entry = 0;
|
||||
}
|
||||
|
||||
Space *SpaceFromEntry(SpaceEntry *entry)
|
||||
PP_Space *PP_SpaceFromEntry(PP_SpaceEntry *entry)
|
||||
{
|
||||
if (entry->valid)
|
||||
{
|
||||
u64 first_entry_addr = (u64)(entry - entry->handle.idx);
|
||||
Space *space = (Space *)(first_entry_addr - SpaceEntriesOffset);
|
||||
Assert(space->entries == (SpaceEntry *)first_entry_addr);
|
||||
PP_Space *space = (PP_Space *)(first_entry_addr - PP_SpaceEntriesOffset);
|
||||
Assert(space->entries == (PP_SpaceEntry *)first_entry_addr);
|
||||
return space;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NilSpace();
|
||||
return PP_NilSpace();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Cell
|
||||
|
||||
Vec2I32 SpaceCellCoordsFromWorldCoords(f32 cell_size, Vec2 world_pos)
|
||||
Vec2I32 PP_SpaceCellCoordsFromWorldCoords(f32 cell_size, Vec2 world_pos)
|
||||
{
|
||||
f32 x = world_pos.x;
|
||||
f32 y = world_pos.y;
|
||||
@ -75,7 +75,7 @@ Vec2I32 SpaceCellCoordsFromWorldCoords(f32 cell_size, Vec2 world_pos)
|
||||
return VEC2I32((i32)x, (i32)y);
|
||||
}
|
||||
|
||||
i32 SpaceBinIndexFromCellCoords(Space *space, Vec2I32 cell_pos)
|
||||
i32 PP_SpaceBinIndexFromCellCoords(PP_Space *space, Vec2I32 cell_pos)
|
||||
{
|
||||
i32 num_bins_sqrt = space->num_bins_sqrt;
|
||||
|
||||
@ -97,12 +97,12 @@ i32 SpaceBinIndexFromCellCoords(Space *space, Vec2I32 cell_pos)
|
||||
return bin_index;
|
||||
}
|
||||
|
||||
SpaceCell *SpaceCellFromCellPos(Space *space, Vec2I32 cell_pos)
|
||||
PP_SpaceCell *PP_SpaceCellFromCellPos(PP_Space *space, Vec2I32 cell_pos)
|
||||
{
|
||||
i32 bin_index = SpaceBinIndexFromCellCoords(space, cell_pos);
|
||||
SpaceCellBin *bin = &space->bins[bin_index];
|
||||
SpaceCell *result = NilSpaceCell();
|
||||
for (SpaceCell *n = bin->first_cell; n; n = n->next_in_bin)
|
||||
i32 bin_index = PP_SpaceBinIndexFromCellCoords(space, cell_pos);
|
||||
PP_SpaceCellBin *bin = &space->bins[bin_index];
|
||||
PP_SpaceCell *result = PP_NilSpaceCell();
|
||||
for (PP_SpaceCell *n = bin->first_cell; n; n = n->next_in_bin)
|
||||
{
|
||||
if (EqVec2I32(n->pos, cell_pos))
|
||||
{
|
||||
@ -113,15 +113,15 @@ SpaceCell *SpaceCellFromCellPos(Space *space, Vec2I32 cell_pos)
|
||||
return result;
|
||||
}
|
||||
|
||||
void AcquireSpaceCellNode(Vec2I32 cell_pos, SpaceEntry *entry)
|
||||
void PP_AcquireSpaceCellNode(Vec2I32 cell_pos, PP_SpaceEntry *entry)
|
||||
{
|
||||
Space *space = SpaceFromEntry(entry);
|
||||
i32 bin_index = SpaceBinIndexFromCellCoords(space, cell_pos);
|
||||
SpaceCellBin *bin = &space->bins[bin_index];
|
||||
PP_Space *space = PP_SpaceFromEntry(entry);
|
||||
i32 bin_index = PP_SpaceBinIndexFromCellCoords(space, cell_pos);
|
||||
PP_SpaceCellBin *bin = &space->bins[bin_index];
|
||||
|
||||
/* Find existing cell */
|
||||
SpaceCell *cell = 0;
|
||||
for (SpaceCell *n = bin->first_cell; n; n = n->next_in_bin)
|
||||
PP_SpaceCell *cell = 0;
|
||||
for (PP_SpaceCell *n = bin->first_cell; n; n = n->next_in_bin)
|
||||
{
|
||||
if (EqVec2I32(n->pos, cell_pos))
|
||||
{
|
||||
@ -140,7 +140,7 @@ void AcquireSpaceCellNode(Vec2I32 cell_pos, SpaceEntry *entry)
|
||||
}
|
||||
else
|
||||
{
|
||||
cell = PushStructNoZero(space->cell_arena, SpaceCell);
|
||||
cell = PushStructNoZero(space->cell_arena, PP_SpaceCell);
|
||||
}
|
||||
ZeroStruct(cell);
|
||||
if (bin->last_cell)
|
||||
@ -159,7 +159,7 @@ void AcquireSpaceCellNode(Vec2I32 cell_pos, SpaceEntry *entry)
|
||||
}
|
||||
|
||||
/* Acquire node */
|
||||
SpaceCellNode *node;
|
||||
PP_SpaceCellNode *node;
|
||||
{
|
||||
if (space->first_free_cell_node)
|
||||
{
|
||||
@ -168,7 +168,7 @@ void AcquireSpaceCellNode(Vec2I32 cell_pos, SpaceEntry *entry)
|
||||
}
|
||||
else
|
||||
{
|
||||
node = PushStructNoZero(space->cell_arena, SpaceCellNode);
|
||||
node = PushStructNoZero(space->cell_arena, PP_SpaceCellNode);
|
||||
}
|
||||
ZeroStruct(node);
|
||||
}
|
||||
@ -200,17 +200,17 @@ void AcquireSpaceCellNode(Vec2I32 cell_pos, SpaceEntry *entry)
|
||||
entry->last_node = node;
|
||||
}
|
||||
|
||||
void ReleaseSpaceCellNode(SpaceCellNode *n)
|
||||
void PP_ReleaseSpaceCellNode(PP_SpaceCellNode *n)
|
||||
{
|
||||
SpaceCell *cell = n->cell;
|
||||
SpaceEntry *entry = n->entry;
|
||||
Space *space = SpaceFromEntry(entry);
|
||||
SpaceCellBin *bin = cell->bin;
|
||||
PP_SpaceCell *cell = n->cell;
|
||||
PP_SpaceEntry *entry = n->entry;
|
||||
PP_Space *space = PP_SpaceFromEntry(entry);
|
||||
PP_SpaceCellBin *bin = cell->bin;
|
||||
|
||||
/* Remove from entry list */
|
||||
{
|
||||
SpaceCellNode *prev = n->prev_in_entry;
|
||||
SpaceCellNode *next = n->next_in_entry;
|
||||
PP_SpaceCellNode *prev = n->prev_in_entry;
|
||||
PP_SpaceCellNode *next = n->next_in_entry;
|
||||
if (prev)
|
||||
{
|
||||
prev->next_in_entry = next;
|
||||
@ -231,8 +231,8 @@ void ReleaseSpaceCellNode(SpaceCellNode *n)
|
||||
|
||||
/* Remove from cell list */
|
||||
{
|
||||
SpaceCellNode *prev = n->prev_in_cell;
|
||||
SpaceCellNode *next = n->next_in_cell;
|
||||
PP_SpaceCellNode *prev = n->prev_in_cell;
|
||||
PP_SpaceCellNode *next = n->next_in_cell;
|
||||
if (prev)
|
||||
{
|
||||
prev->next_in_cell = next;
|
||||
@ -255,8 +255,8 @@ void ReleaseSpaceCellNode(SpaceCellNode *n)
|
||||
if (!cell->first_node && !cell->last_node)
|
||||
{
|
||||
/* Remove from bin */
|
||||
SpaceCell *prev = cell->prev_in_bin;
|
||||
SpaceCell *next = cell->next_in_bin;
|
||||
PP_SpaceCell *prev = cell->prev_in_bin;
|
||||
PP_SpaceCell *next = cell->next_in_bin;
|
||||
if (prev)
|
||||
{
|
||||
prev->next_in_bin = next;
|
||||
@ -288,13 +288,13 @@ void ReleaseSpaceCellNode(SpaceCellNode *n)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Entry
|
||||
|
||||
SpaceEntry *SpaceEntryFromHandle(Space *space, SpaceEntryHandle handle)
|
||||
PP_SpaceEntry *PP_SpaceEntryFromKey(PP_Space *space, PP_SpaceEntryKey handle)
|
||||
{
|
||||
SpaceEntry *entry = NilSpaceEntry();
|
||||
PP_SpaceEntry *entry = PP_NilSpaceEntry();
|
||||
|
||||
if (handle.gen > 0 && handle.idx < space->num_entries_reserved)
|
||||
{
|
||||
SpaceEntry *tmp = &space->entries[handle.idx];
|
||||
PP_SpaceEntry *tmp = &space->entries[handle.idx];
|
||||
if (tmp->handle.gen == handle.gen)
|
||||
{
|
||||
entry = tmp;
|
||||
@ -304,10 +304,10 @@ SpaceEntry *SpaceEntryFromHandle(Space *space, SpaceEntryHandle handle)
|
||||
return entry;
|
||||
}
|
||||
|
||||
SpaceEntry *AcquireSpaceEntry(Space *space, EntityId ent)
|
||||
PP_SpaceEntry *PP_AcquireSpaceEntry(PP_Space *space, PP_EntKey ent)
|
||||
{
|
||||
SpaceEntry *entry = 0;
|
||||
SpaceEntryHandle handle = ZI;
|
||||
PP_SpaceEntry *entry = 0;
|
||||
PP_SpaceEntryKey handle = ZI;
|
||||
if (space->first_free_entry)
|
||||
{
|
||||
entry = space->first_free_entry;
|
||||
@ -316,7 +316,7 @@ SpaceEntry *AcquireSpaceEntry(Space *space, EntityId ent)
|
||||
}
|
||||
else
|
||||
{
|
||||
entry = PushStructNoZero(space->entry_arena, SpaceEntry);
|
||||
entry = PushStructNoZero(space->entry_arena, PP_SpaceEntry);
|
||||
handle.idx = space->num_entries_reserved;
|
||||
handle.gen = 1;
|
||||
++space->num_entries_reserved;
|
||||
@ -328,28 +328,28 @@ SpaceEntry *AcquireSpaceEntry(Space *space, EntityId ent)
|
||||
return entry;
|
||||
}
|
||||
|
||||
void ReleaseSpaceEntry(SpaceEntry *entry)
|
||||
void PP_ReleaseSpaceEntry(PP_SpaceEntry *entry)
|
||||
{
|
||||
/* Release nodes */
|
||||
SpaceCellNode *n = entry->first_node;
|
||||
PP_SpaceCellNode *n = entry->first_node;
|
||||
while (n)
|
||||
{
|
||||
SpaceCellNode *next = n->next_in_entry;
|
||||
PP_SpaceCellNode *next = n->next_in_entry;
|
||||
/* TODO: More efficient batch release that doesn't care about maintaining entry list */
|
||||
ReleaseSpaceCellNode(n);
|
||||
PP_ReleaseSpaceCellNode(n);
|
||||
n = next;
|
||||
}
|
||||
|
||||
Space *space = SpaceFromEntry(entry);
|
||||
PP_Space *space = PP_SpaceFromEntry(entry);
|
||||
entry->next_free = space->first_free_entry;
|
||||
entry->valid = 0;
|
||||
++entry->handle.gen;
|
||||
space->first_free_entry = entry;
|
||||
}
|
||||
|
||||
void UpdateSpaceEntryAabb(SpaceEntry *entry, Aabb new_aabb)
|
||||
void PP_UpdateSpaceEntryAabb(PP_SpaceEntry *entry, Aabb new_aabb)
|
||||
{
|
||||
Space *space = SpaceFromEntry(entry);
|
||||
PP_Space *space = PP_SpaceFromEntry(entry);
|
||||
f32 cell_size = space->cell_size;
|
||||
|
||||
Vec2I32 old_cell_p0 = VEC2I32(0, 0);
|
||||
@ -357,24 +357,24 @@ void UpdateSpaceEntryAabb(SpaceEntry *entry, Aabb new_aabb)
|
||||
if (entry->first_node)
|
||||
{
|
||||
Aabb old_aabb = entry->aabb;
|
||||
old_cell_p0 = SpaceCellCoordsFromWorldCoords(cell_size, old_aabb.p0);
|
||||
old_cell_p1 = SpaceCellCoordsFromWorldCoords(cell_size, old_aabb.p1);
|
||||
old_cell_p0 = PP_SpaceCellCoordsFromWorldCoords(cell_size, old_aabb.p0);
|
||||
old_cell_p1 = PP_SpaceCellCoordsFromWorldCoords(cell_size, old_aabb.p1);
|
||||
}
|
||||
|
||||
Vec2I32 new_cell_p0 = SpaceCellCoordsFromWorldCoords(cell_size, new_aabb.p0);
|
||||
Vec2I32 new_cell_p1 = SpaceCellCoordsFromWorldCoords(cell_size, new_aabb.p1);
|
||||
Vec2I32 new_cell_p0 = PP_SpaceCellCoordsFromWorldCoords(cell_size, new_aabb.p0);
|
||||
Vec2I32 new_cell_p1 = PP_SpaceCellCoordsFromWorldCoords(cell_size, new_aabb.p1);
|
||||
|
||||
/* Release outdated nodes */
|
||||
SpaceCellNode *n = entry->first_node;
|
||||
PP_SpaceCellNode *n = entry->first_node;
|
||||
while (n)
|
||||
{
|
||||
SpaceCell *cell = n->cell;
|
||||
PP_SpaceCell *cell = n->cell;
|
||||
Vec2I32 cell_pos = cell->pos;
|
||||
if (cell_pos.x < new_cell_p0.x || cell_pos.x > new_cell_p1.x || cell_pos.y < new_cell_p0.y || cell_pos.y > new_cell_p1.y)
|
||||
{
|
||||
/* Cell is outside of new AABB */
|
||||
SpaceCellNode *next = n->next_in_entry;
|
||||
ReleaseSpaceCellNode(n);
|
||||
PP_SpaceCellNode *next = n->next_in_entry;
|
||||
PP_ReleaseSpaceCellNode(n);
|
||||
n = next;
|
||||
}
|
||||
else
|
||||
@ -391,7 +391,7 @@ void UpdateSpaceEntryAabb(SpaceEntry *entry, Aabb new_aabb)
|
||||
if (x != 0 && y != 0 && (x < old_cell_p0.x || x > old_cell_p1.x || y < old_cell_p0.y || y > old_cell_p1.y))
|
||||
{
|
||||
/* Cell is outside of old AABB */
|
||||
AcquireSpaceCellNode(VEC2I32(x, y), entry);
|
||||
PP_AcquireSpaceCellNode(VEC2I32(x, y), entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -402,14 +402,14 @@ void UpdateSpaceEntryAabb(SpaceEntry *entry, Aabb new_aabb)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Iter
|
||||
|
||||
SpaceIter BeginSpaceIterAabb(Space *space, Aabb aabb)
|
||||
PP_SpaceIter PP_BeginSpaceIterAabb(PP_Space *space, Aabb aabb)
|
||||
{
|
||||
SpaceIter iter = ZI;
|
||||
PP_SpaceIter iter = ZI;
|
||||
f32 cell_size = space->cell_size;
|
||||
|
||||
iter.space = space;
|
||||
iter.cell_start = SpaceCellCoordsFromWorldCoords(cell_size, aabb.p0);
|
||||
iter.cell_end = SpaceCellCoordsFromWorldCoords(cell_size, aabb.p1);
|
||||
iter.cell_start = PP_SpaceCellCoordsFromWorldCoords(cell_size, aabb.p0);
|
||||
iter.cell_end = PP_SpaceCellCoordsFromWorldCoords(cell_size, aabb.p1);
|
||||
if (iter.cell_start.x > iter.cell_end.x || iter.cell_start.y > iter.cell_end.y)
|
||||
{
|
||||
/* Swap cell_start & cell_end */
|
||||
@ -426,16 +426,16 @@ SpaceIter BeginSpaceIterAabb(Space *space, Aabb aabb)
|
||||
return iter;
|
||||
}
|
||||
|
||||
SpaceEntry *NextSpaceIterAabb(SpaceIter *iter)
|
||||
PP_SpaceEntry *PP_NextSpaceIterAabb(PP_SpaceIter *iter)
|
||||
{
|
||||
Space *space = iter->space;
|
||||
PP_Space *space = iter->space;
|
||||
Aabb iter_aabb = iter->aabb;
|
||||
Vec2I32 cell_start = iter->cell_start;
|
||||
Vec2I32 cell_end = iter->cell_end;
|
||||
Vec2I32 cell_cur = iter->cell_cur;
|
||||
i32 span = cell_end.x - cell_start.x;
|
||||
|
||||
SpaceCellNode *next_node = 0;
|
||||
PP_SpaceCellNode *next_node = 0;
|
||||
if (cell_cur.x >= cell_start.x && cell_cur.x <= cell_end.x && cell_cur.y >= cell_start.y && cell_cur.y <= cell_end.y)
|
||||
{
|
||||
/* Started */
|
||||
@ -452,7 +452,7 @@ SpaceEntry *NextSpaceIterAabb(SpaceIter *iter)
|
||||
{
|
||||
if (next_node)
|
||||
{
|
||||
SpaceEntry *entry = next_node->entry;
|
||||
PP_SpaceEntry *entry = next_node->entry;
|
||||
Aabb entry_aabb = entry->aabb;
|
||||
if (CLD_TestAabb(entry_aabb, iter_aabb))
|
||||
{
|
||||
@ -474,7 +474,7 @@ SpaceEntry *NextSpaceIterAabb(SpaceIter *iter)
|
||||
cell_cur.y += nexty;
|
||||
cell_cur.x += (cell_cur.x == 0);
|
||||
cell_cur.y += (cell_cur.y == 0);
|
||||
SpaceCell *cell = SpaceCellFromCellPos(space, cell_cur);
|
||||
PP_SpaceCell *cell = PP_SpaceCellFromCellPos(space, cell_cur);
|
||||
next_node = cell->first_node;
|
||||
}
|
||||
else
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Space entry types
|
||||
|
||||
Struct(SpaceEntryHandle)
|
||||
Struct(PP_SpaceEntryKey)
|
||||
{
|
||||
u64 idx;
|
||||
u64 gen;
|
||||
};
|
||||
|
||||
Struct(SpaceEntry)
|
||||
Struct(PP_SpaceEntry)
|
||||
{
|
||||
b32 valid;
|
||||
SpaceEntryHandle handle;
|
||||
PP_SpaceEntryKey handle;
|
||||
|
||||
struct SpaceCellNode *first_node;
|
||||
struct SpaceCellNode *last_node;
|
||||
struct PP_SpaceCellNode *first_node;
|
||||
struct PP_SpaceCellNode *last_node;
|
||||
|
||||
Aabb aabb;
|
||||
EntityId ent;
|
||||
PP_EntKey ent;
|
||||
|
||||
SpaceEntry *next_free;
|
||||
PP_SpaceEntry *next_free;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -26,134 +26,134 @@ Struct(SpaceEntry)
|
||||
|
||||
/* Links a cell to a entry.
|
||||
* Acts as both a node in the list of entries contained by the cell, and a node in the list of cells containing the entry. */
|
||||
Struct(SpaceCellNode)
|
||||
Struct(PP_SpaceCellNode)
|
||||
{
|
||||
SpaceEntry *entry;
|
||||
struct SpaceCell *cell;
|
||||
PP_SpaceEntry *entry;
|
||||
struct PP_SpaceCell *cell;
|
||||
|
||||
/* For list of all entries contained by cell */
|
||||
SpaceCellNode *prev_in_cell;
|
||||
SpaceCellNode *next_in_cell;
|
||||
PP_SpaceCellNode *prev_in_cell;
|
||||
PP_SpaceCellNode *next_in_cell;
|
||||
|
||||
/* For list of all cells containing entry */
|
||||
SpaceCellNode *prev_in_entry;
|
||||
SpaceCellNode *next_in_entry;
|
||||
PP_SpaceCellNode *prev_in_entry;
|
||||
PP_SpaceCellNode *next_in_entry;
|
||||
|
||||
SpaceCellNode *next_free;
|
||||
PP_SpaceCellNode *next_free;
|
||||
};
|
||||
|
||||
Struct(SpaceCell)
|
||||
Struct(PP_SpaceCell)
|
||||
{
|
||||
b32 valid;
|
||||
Vec2I32 pos;
|
||||
|
||||
SpaceCellNode *first_node;
|
||||
SpaceCellNode *last_node;
|
||||
PP_SpaceCellNode *first_node;
|
||||
PP_SpaceCellNode *last_node;
|
||||
|
||||
struct SpaceCellBin *bin;
|
||||
SpaceCell *prev_in_bin;
|
||||
SpaceCell *next_in_bin;
|
||||
struct PP_SpaceCellBin *bin;
|
||||
PP_SpaceCell *prev_in_bin;
|
||||
PP_SpaceCell *next_in_bin;
|
||||
|
||||
SpaceCell *next_free;
|
||||
PP_SpaceCell *next_free;
|
||||
};
|
||||
|
||||
Struct(SpaceCellBin)
|
||||
Struct(PP_SpaceCellBin)
|
||||
{
|
||||
SpaceCell *first_cell;
|
||||
SpaceCell *last_cell;
|
||||
PP_SpaceCell *first_cell;
|
||||
PP_SpaceCell *last_cell;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Space types
|
||||
|
||||
Struct(Space)
|
||||
Struct(PP_Space)
|
||||
{
|
||||
b32 valid;
|
||||
f32 cell_size;
|
||||
|
||||
Arena *cell_arena;
|
||||
SpaceCellBin *bins;
|
||||
PP_SpaceCellBin *bins;
|
||||
i32 num_bins;
|
||||
i32 num_bins_sqrt;
|
||||
SpaceCell *first_free_cell;
|
||||
SpaceCellNode *first_free_cell_node;
|
||||
PP_SpaceCell *first_free_cell;
|
||||
PP_SpaceCellNode *first_free_cell_node;
|
||||
|
||||
Arena *entry_arena;
|
||||
u64 num_entries_reserved;
|
||||
SpaceEntry *entries;
|
||||
SpaceEntry *first_free_entry;
|
||||
PP_SpaceEntry *entries;
|
||||
PP_SpaceEntry *first_free_entry;
|
||||
};
|
||||
|
||||
Struct(SpaceIter)
|
||||
Struct(PP_SpaceIter)
|
||||
{
|
||||
Aabb aabb;
|
||||
Space *space;
|
||||
PP_Space *space;
|
||||
Vec2I32 cell_start;
|
||||
Vec2I32 cell_end;
|
||||
Vec2I32 cell_cur;
|
||||
SpaceCellNode *prev;
|
||||
PP_SpaceCellNode *prev;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Nil types
|
||||
|
||||
/* Offset in bytes from start of space struct to start of entry array (assume adjacently allocated) */
|
||||
#define SpaceEntriesOffset (sizeof(Space) + (sizeof(Space) % alignof(SpaceEntry)))
|
||||
#define PP_SpaceEntriesOffset (sizeof(PP_Space) + (sizeof(PP_Space) % alignof(PP_SpaceEntry)))
|
||||
|
||||
/* Accessed via NilEntity() */
|
||||
extern Readonly SpaceEntry _g_space_entry_nil;
|
||||
extern Readonly SpaceCell _g_space_cell_nil;
|
||||
extern Readonly Space _g_space_nil;
|
||||
/* Accessed via NilEnt() */
|
||||
extern Readonly PP_SpaceEntry PP_nil_space_entry;
|
||||
extern Readonly PP_SpaceCell PP_nil_space_cell;
|
||||
extern Readonly PP_Space PP_nil_space;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Nil helpers
|
||||
|
||||
Inline SpaceEntry *NilSpaceEntry(void)
|
||||
Inline PP_SpaceEntry *PP_NilSpaceEntry(void)
|
||||
{
|
||||
extern Readonly SpaceEntry _g_space_entry_nil;
|
||||
return &_g_space_entry_nil;
|
||||
extern Readonly PP_SpaceEntry PP_nil_space_entry;
|
||||
return &PP_nil_space_entry;
|
||||
}
|
||||
|
||||
Inline SpaceCell *NilSpaceCell(void)
|
||||
Inline PP_SpaceCell *PP_NilSpaceCell(void)
|
||||
{
|
||||
extern Readonly SpaceCell _g_space_cell_nil;
|
||||
return &_g_space_cell_nil;
|
||||
extern Readonly PP_SpaceCell PP_nil_space_cell;
|
||||
return &PP_nil_space_cell;
|
||||
}
|
||||
|
||||
Inline Space *NilSpace(void)
|
||||
Inline PP_Space *PP_NilSpace(void)
|
||||
{
|
||||
extern Readonly Space _g_space_nil;
|
||||
return &_g_space_nil;
|
||||
extern Readonly PP_Space PP_nil_space;
|
||||
return &PP_nil_space;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Space
|
||||
|
||||
Space *AcquireSpace(f32 cell_size, u32 num_bins_sqrt);
|
||||
void ReleaseSpace(Space *space);
|
||||
void ResetSpace(Space *space);
|
||||
Space *SpaceFromEntry(SpaceEntry *entry);
|
||||
PP_Space *PP_AcquireSpace(f32 cell_size, u32 num_bins_sqrt);
|
||||
void PP_ReleaseSpace(PP_Space *space);
|
||||
void PP_ResetSpace(PP_Space *space);
|
||||
PP_Space *PP_SpaceFromEntry(PP_SpaceEntry *entry);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Cell
|
||||
|
||||
Vec2I32 SpaceCellCoordsFromWorldCoords(f32 cell_size, Vec2 world_pos);
|
||||
i32 SpaceBinIndexFromCellCoords(Space *space, Vec2I32 cell_pos);
|
||||
SpaceCell *SpaceCellFromCellPos(Space *space, Vec2I32 cell_pos);
|
||||
void AcquireSpaceCellNode(Vec2I32 cell_pos, SpaceEntry *entry);
|
||||
void ReleaseSpaceCellNode(SpaceCellNode *n);
|
||||
Vec2I32 PP_SpaceCellCoordsFromWorldCoords(f32 cell_size, Vec2 world_pos);
|
||||
i32 PP_SpaceBinIndexFromCellCoords(PP_Space *space, Vec2I32 cell_pos);
|
||||
PP_SpaceCell *PP_SpaceCellFromCellPos(PP_Space *space, Vec2I32 cell_pos);
|
||||
void PP_AcquireSpaceCellNode(Vec2I32 cell_pos, PP_SpaceEntry *entry);
|
||||
void PP_ReleaseSpaceCellNode(PP_SpaceCellNode *n);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Entry
|
||||
|
||||
SpaceEntry *SpaceEntryFromHandle(Space *space, SpaceEntryHandle handle);
|
||||
SpaceEntry *AcquireSpaceEntry(Space *space, EntityId ent);
|
||||
void ReleaseSpaceEntry(SpaceEntry *entry);
|
||||
void UpdateSpaceEntryAabb(SpaceEntry *entry, Aabb new_aabb);
|
||||
PP_SpaceEntry *PP_SpaceEntryFromKey(PP_Space *space, PP_SpaceEntryKey handle);
|
||||
PP_SpaceEntry *PP_AcquireSpaceEntry(PP_Space *space, PP_EntKey ent);
|
||||
void PP_ReleaseSpaceEntry(PP_SpaceEntry *entry);
|
||||
void PP_UpdateSpaceEntryAabb(PP_SpaceEntry *entry, Aabb new_aabb);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Iter
|
||||
|
||||
SpaceIter BeginSpaceIterAabb(Space *space, Aabb aabb);
|
||||
SpaceEntry *NextSpaceIterAabb(SpaceIter *iter);
|
||||
#define EndSpaceIter(i)
|
||||
PP_SpaceIter PP_BeginSpaceIterAabb(PP_Space *space, Aabb aabb);
|
||||
PP_SpaceEntry *PP_NextSpaceIterAabb(PP_SpaceIter *iter);
|
||||
#define PP_EndSpaceIter(i)
|
||||
|
||||
890
src/pp/pp_step.c
890
src/pp/pp_step.c
File diff suppressed because it is too large
Load Diff
@ -4,65 +4,65 @@
|
||||
/* Structure used to accelerate up entity lookup (rebuilt every step) */
|
||||
/* TODO: Remove this and do something better. Just a hack to de-couple old sim ctx from step. */
|
||||
|
||||
Struct(SimAccel)
|
||||
Struct(PP_Accel)
|
||||
{
|
||||
Space *space;
|
||||
PP_Space *space;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Step ctx
|
||||
|
||||
Struct(SimStepCtx)
|
||||
Struct(PP_SimStepCtx)
|
||||
{
|
||||
b32 is_master;
|
||||
SimAccel *accel;
|
||||
PP_Accel *accel;
|
||||
RandState rand; /* TODO: Replace with per-sim rand for deterministic rng */
|
||||
|
||||
Snapshot *world; /* The world to simulate */
|
||||
PP_Snapshot *world; /* The world to simulate */
|
||||
i64 sim_dt_ns; /* How much sim time should progress */
|
||||
|
||||
Client *user_input_client; /* The client that contains input from the user thread */
|
||||
Client *master_client; /* The master client to read snapshots from (nil if world is master) */
|
||||
Client *publish_client; /* The publish client to write syncable state to (nil if skipping publish) */
|
||||
PP_Client *user_input_client; /* The client that contains input from the user thread */
|
||||
PP_Client *master_client; /* The master client to read snapshots from (nil if world is master) */
|
||||
PP_Client *publish_client; /* The publish client to write syncable state to (nil if skipping publish) */
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Accel operations
|
||||
|
||||
SimAccel AcquireSimAccel(void);
|
||||
void ReleaseSimAccel(SimAccel *accel);
|
||||
void ResetSimAccel(Snapshot *ss, SimAccel *accel);
|
||||
PP_Accel PP_AcquireAccel(void);
|
||||
void PP_ReleaseAccel(PP_Accel *accel);
|
||||
void PP_ResetAccel(PP_Snapshot *ss, PP_Accel *accel);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Spawn test operations
|
||||
|
||||
Entity *SpawnTestSmg(Entity *parent);
|
||||
Entity *SpawnTestLauncher(Entity *parent);
|
||||
Entity *SpawnTestChucker(Entity *parent);
|
||||
Entity *SpawnTestEmployee(Entity *parent);
|
||||
Entity *SpawnTestCamera(Entity *parent, Entity *follow);
|
||||
Entity *SpawnTestExplosion(Entity *parent, Vec2 pos, f32 strength, f32 radius);
|
||||
void TeleportTest(Entity *ent, Vec2 pos);
|
||||
void SpawnTestEntities1(Entity *parent, Vec2 pos);
|
||||
void SpawnTestEntities2(Entity *parent, Vec2 pos);
|
||||
void SpawnTestEntities3(Entity *parent, Vec2 pos);
|
||||
void SpawnTestEntities4(Entity *parent, Vec2 pos);
|
||||
void SpawnTestTile(Snapshot *world, Vec2 world_pos);
|
||||
void ClearLevelTest(SimStepCtx *ctx);
|
||||
PP_Ent *PP_SpawnTestSmg(PP_Ent *parent);
|
||||
PP_Ent *PP_SpawnTestLauncher(PP_Ent *parent);
|
||||
PP_Ent *PP_SpawnTestChucker(PP_Ent *parent);
|
||||
PP_Ent *PP_SpawnTestEmployee(PP_Ent *parent);
|
||||
PP_Ent *PP_SpawnTestCamera(PP_Ent *parent, PP_Ent *follow);
|
||||
PP_Ent *PP_SpawnTestExplosion(PP_Ent *parent, Vec2 pos, f32 strength, f32 radius);
|
||||
void PP_TeleportTest(PP_Ent *ent, Vec2 pos);
|
||||
void PP_SpawnTestEnts1(PP_Ent *parent, Vec2 pos);
|
||||
void PP_SpawnTestEnts2(PP_Ent *parent, Vec2 pos);
|
||||
void PP_SpawnTestEnts3(PP_Ent *parent, Vec2 pos);
|
||||
void PP_SpawnTestEnts4(PP_Ent *parent, Vec2 pos);
|
||||
void PP_SpawnTestTile(PP_Snapshot *world, Vec2 world_pos);
|
||||
void PP_ClearLevelTest(PP_SimStepCtx *ctx);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Tile test operations
|
||||
|
||||
MergesortCompareFuncDef(SortTileXCmp, arg_a, arg_b, _);
|
||||
MergesortCompareFuncDef(SortTileYCmp, arg_a, arg_b, _);
|
||||
void GenerateTestWalls(Snapshot *world);
|
||||
MergesortCompareFuncDef(PP_SortTileXCmp, arg_a, arg_b, _);
|
||||
MergesortCompareFuncDef(PP_SortTileYCmp, arg_a, arg_b, _);
|
||||
void PP_GenerateTestWalls(PP_Snapshot *world);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Collision response
|
||||
|
||||
CollisionCallbackFuncDef(OnEntityCollision, data, step_ctx);
|
||||
PP_CollisionCallbackFuncDef(PP_OnEntCollision, data, step_ctx);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Step
|
||||
|
||||
void StepSim(SimStepCtx *ctx);
|
||||
void PP_StepSim(PP_SimStepCtx *ctx);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user