entity observation cache
This commit is contained in:
parent
a6f9bcf4f3
commit
039e354a9d
@ -84,6 +84,7 @@ Struct(P_DebugDrawNode)
|
||||
#define P_RollTimeNs NsFromSeconds(0.5)
|
||||
#define P_RollTurnTimeNs (NsFromSeconds(0.1))
|
||||
#define P_RollTimeoutNs NsFromSeconds(0.5)
|
||||
#define P_ObservationLifetimeNs NsFromSeconds(2)
|
||||
|
||||
Struct(P_Control)
|
||||
{
|
||||
@ -118,6 +119,11 @@ Struct(P_Ent)
|
||||
i64 created_at_tick;
|
||||
f64 lifetime_seconds;
|
||||
|
||||
//- Client data
|
||||
|
||||
i64 local_observation_ns;
|
||||
b32 has_observed;
|
||||
|
||||
//- Build data
|
||||
|
||||
u64 continuity_gen;
|
||||
|
||||
@ -1892,6 +1892,61 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Observe entities
|
||||
|
||||
{
|
||||
for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||
{
|
||||
P_EntKey key = ent->key;
|
||||
i64 expiration_ns = P_ObservationLifetimeNs;
|
||||
i64 observation_time_ns = 0;
|
||||
{
|
||||
V_ObservationBin *bin = &V.observation_bins[key.v % countof(V.observation_bins)];
|
||||
V_Observation *obs = bin->first;
|
||||
for (; obs; obs = obs->next)
|
||||
{
|
||||
if (obs->key == key.v)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (obs)
|
||||
{
|
||||
if (obs->time_ns + expiration_ns > frame->time_ns)
|
||||
{
|
||||
// Re-observe expired observation
|
||||
DllQueueRemove(V.first_observation, V.last_observation, obs);
|
||||
DllQueuePush(V.first_observation, V.last_observation, obs);
|
||||
obs->time_ns = frame->time_ns;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (V.first_observation && V.first_observation->time_ns + expiration_ns <= frame->time_ns)
|
||||
{
|
||||
// Remove expired observation for reuse
|
||||
obs = V.first_observation;
|
||||
V_ObservationBin *old_bin = &V.observation_bins[obs->key % countof(V.observation_bins)];
|
||||
DllQueueRemove(V.first_observation, V.last_observation, obs);
|
||||
DllQueueRemoveNP(old_bin->first, old_bin->last, obs, next_in_bin, prev_in_bin);
|
||||
}
|
||||
else
|
||||
{
|
||||
obs = PushStruct(perm, V_Observation);
|
||||
}
|
||||
obs->key = key.v;
|
||||
obs->time_ns = frame->time_ns;
|
||||
DllQueuePush(V.first_observation, V.last_observation, obs);
|
||||
DllQueuePushNP(bin->first, bin->last, obs, next_in_bin, prev_in_bin);
|
||||
}
|
||||
observation_time_ns = obs->time_ns;
|
||||
}
|
||||
ent->local_observation_ns = observation_time_ns;
|
||||
ent->has_observed = observation_time_ns == frame->time_ns;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -2341,72 +2396,165 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Push test bullet particles
|
||||
//- Push bullet trail particles
|
||||
|
||||
// TODO: Not like this
|
||||
|
||||
for (P_Ent *bullet = P_FirstEnt(local_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||
{
|
||||
if (bullet->is_bullet)
|
||||
{
|
||||
// FIXME: Use 'last visible' pos
|
||||
P_Ent *old_bullet = P_EntFromKey(prev_local_frame, bullet->key);
|
||||
Vec2 start = old_bullet->xf.t;
|
||||
Vec2 end = bullet->xf.t;
|
||||
if (P_IsEntNil(old_bullet))
|
||||
{
|
||||
start = end;
|
||||
}
|
||||
// for (P_Ent *trail = P_FirstEnt(local_frame); !P_IsEntNil(trail); trail = P_NextEnt(trail))
|
||||
// {
|
||||
// if (trail->is_trail)
|
||||
// {
|
||||
// // FIXME: Use 'last visible' pos
|
||||
// P_Ent *old_bullet = P_EntFromKey(prev_local_frame, bullet->key);
|
||||
// Vec2 start = old_bullet->xf.t;
|
||||
// Vec2 end = bullet->xf.t;
|
||||
// if (P_IsEntNil(old_bullet))
|
||||
// {
|
||||
// start = end;
|
||||
// }
|
||||
|
||||
b32 skip = 0;
|
||||
if (bullet->has_hit)
|
||||
{
|
||||
Vec2 hit_pos = bullet->hit_entry;
|
||||
if (DotVec2(SubVec2(hit_pos, start), SubVec2(end, start)) < 0)
|
||||
{
|
||||
skip = 1;
|
||||
}
|
||||
// V_DrawPoint(MulAffineVec2(frame->af.world_to_screen, start), Color_Red);
|
||||
// V_DrawPoint(MulAffineVec2(frame->af.world_to_screen, end), Color_Purple);
|
||||
end = hit_pos;
|
||||
}
|
||||
// b32 skip = 0;
|
||||
// if (bullet->has_hit)
|
||||
// {
|
||||
// Vec2 hit_pos = bullet->hit_entry;
|
||||
// if (DotVec2(SubVec2(hit_pos, start), SubVec2(end, start)) < 0)
|
||||
// {
|
||||
// skip = 1;
|
||||
// }
|
||||
// // V_DrawPoint(MulAffineVec2(frame->af.world_to_screen, start), Color_Red);
|
||||
// // V_DrawPoint(MulAffineVec2(frame->af.world_to_screen, end), Color_Purple);
|
||||
// end = hit_pos;
|
||||
// }
|
||||
|
||||
if (!skip)
|
||||
{
|
||||
{
|
||||
f32 trail_len = Vec2Len(SubVec2(end, start));
|
||||
f32 particles_count = trail_len * frame->dt * Kibi(8); // Particles per meter per second
|
||||
particles_count = MaxF32(particles_count, 1);
|
||||
// if (!skip)
|
||||
// {
|
||||
// {
|
||||
// f32 trail_len = Vec2Len(SubVec2(end, start));
|
||||
// f32 particles_count = trail_len * frame->dt * Kibi(8); // Particles per meter per second
|
||||
// particles_count = MaxF32(particles_count, 1);
|
||||
|
||||
f32 angle = AngleFromVec2(PerpVec2(SubVec2(end, start)));
|
||||
// f32 angle = AngleFromVec2(NegVec2(SubVec2(end, start)));
|
||||
// f32 angle = AngleFromVec2(PerpVec2(SubVec2(end, start)));
|
||||
// // f32 angle = AngleFromVec2(NegVec2(SubVec2(end, start)));
|
||||
|
||||
V_Emitter emitter = Zi;
|
||||
{
|
||||
emitter.kind = V_ParticleKind_BulletTrail;
|
||||
emitter.count = particles_count;
|
||||
// V_Emitter emitter = Zi;
|
||||
// {
|
||||
// emitter.kind = V_ParticleKind_BulletTrail;
|
||||
// emitter.count = particles_count;
|
||||
|
||||
f32 angle_spread = Tau / 4.0;
|
||||
// f32 angle_spread = Tau / 4.0;
|
||||
|
||||
emitter.angle.min = angle - angle_spread / 2;
|
||||
emitter.angle.max = angle + angle_spread / 2;
|
||||
// emitter.angle.min = angle - angle_spread / 2;
|
||||
// emitter.angle.max = angle + angle_spread / 2;
|
||||
|
||||
emitter.pos.p0 = start;
|
||||
emitter.pos.p1 = end;
|
||||
// emitter.pos.p0 = start;
|
||||
// emitter.pos.p1 = end;
|
||||
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1));
|
||||
// // emitter.color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1));
|
||||
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.6, 0.2, 1));
|
||||
// // emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.6, 0.2, 1));
|
||||
|
||||
emitter.speed.min = -1;
|
||||
emitter.speed.max = 1;
|
||||
}
|
||||
V_PushParticles(emitter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// emitter.speed.min = -1;
|
||||
// emitter.speed.max = 1;
|
||||
// }
|
||||
// V_PushParticles(emitter);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// //////////////////////////////
|
||||
// //- Push test bullet particles
|
||||
|
||||
// // TODO: Not like this
|
||||
|
||||
// for (P_Ent *bullet = P_FirstEnt(local_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||
// {
|
||||
// if (bullet->is_bullet)
|
||||
// {
|
||||
// // FIXME: Use 'last visible' pos
|
||||
// P_Ent *old_bullet = P_EntFromKey(prev_local_frame, bullet->key);
|
||||
// Vec2 start = old_bullet->xf.t;
|
||||
// Vec2 end = bullet->xf.t;
|
||||
// if (P_IsEntNil(old_bullet))
|
||||
// {
|
||||
// start = end;
|
||||
// }
|
||||
|
||||
// b32 skip = 0;
|
||||
// if (bullet->has_hit)
|
||||
// {
|
||||
// Vec2 hit_pos = bullet->hit_entry;
|
||||
// if (DotVec2(SubVec2(hit_pos, start), SubVec2(end, start)) < 0)
|
||||
// {
|
||||
// skip = 1;
|
||||
// }
|
||||
// // V_DrawPoint(MulAffineVec2(frame->af.world_to_screen, start), Color_Red);
|
||||
// // V_DrawPoint(MulAffineVec2(frame->af.world_to_screen, end), Color_Purple);
|
||||
// end = hit_pos;
|
||||
// }
|
||||
|
||||
// if (!skip)
|
||||
// {
|
||||
// {
|
||||
// f32 trail_len = Vec2Len(SubVec2(end, start));
|
||||
// f32 particles_count = trail_len * frame->dt * Kibi(8); // Particles per meter per second
|
||||
// particles_count = MaxF32(particles_count, 1);
|
||||
|
||||
// f32 angle = AngleFromVec2(PerpVec2(SubVec2(end, start)));
|
||||
// // f32 angle = AngleFromVec2(NegVec2(SubVec2(end, start)));
|
||||
|
||||
// V_Emitter emitter = Zi;
|
||||
// {
|
||||
// emitter.kind = V_ParticleKind_BulletTrail;
|
||||
// emitter.count = particles_count;
|
||||
|
||||
// f32 angle_spread = Tau / 4.0;
|
||||
|
||||
// emitter.angle.min = angle - angle_spread / 2;
|
||||
// emitter.angle.max = angle + angle_spread / 2;
|
||||
|
||||
// emitter.pos.p0 = start;
|
||||
// emitter.pos.p1 = end;
|
||||
|
||||
// // emitter.color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1));
|
||||
|
||||
// // emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.6, 0.2, 1));
|
||||
|
||||
// emitter.speed.min = -1;
|
||||
// emitter.speed.max = 1;
|
||||
// }
|
||||
// V_PushParticles(emitter);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
@ -2615,6 +2763,10 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Push test explosion
|
||||
|
||||
|
||||
@ -227,6 +227,27 @@ Struct(V_TimelineMarker)
|
||||
f64 tick;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Observation types
|
||||
|
||||
#define V_ObservationBinsCount Kibi(32)
|
||||
|
||||
Struct(V_Observation)
|
||||
{
|
||||
V_Observation *next;
|
||||
V_Observation *prev;
|
||||
V_Observation *next_in_bin;
|
||||
V_Observation *prev_in_bin;
|
||||
u64 key;
|
||||
i64 time_ns;
|
||||
};
|
||||
|
||||
Struct(V_ObservationBin)
|
||||
{
|
||||
V_Observation *first;
|
||||
V_Observation *last;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ State types
|
||||
|
||||
@ -283,6 +304,10 @@ Struct(V_Ctx)
|
||||
|
||||
i64 connect_try_ns;
|
||||
|
||||
V_ObservationBin observation_bins[V_ObservationBinsCount];
|
||||
V_Observation *first_observation;
|
||||
V_Observation *last_observation;
|
||||
|
||||
// Notifications
|
||||
V_Notif *first_notif;
|
||||
V_Notif *last_notif;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user