From 3dc22b9bd791b8df6ed721b814b3232534a6da36 Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 7 Jan 2026 04:34:53 -0600 Subject: [PATCH] bullet trail testing --- src/base/base.cgh | 7 +- src/pp/pp_sim/pp_sim_core.c | 37 +++++++++- src/pp/pp_sim/pp_sim_core.h | 6 ++ src/pp/pp_sim/pp_sim_transcode.c | 9 +++ src/pp/pp_vis/pp_vis_core.c | 116 +++++++++++++++++++++++++++---- src/pp/pp_vis/pp_vis_gpu.g | 42 +++++------ src/pp/pp_vis/pp_vis_shared.cgh | 7 +- 7 files changed, 186 insertions(+), 38 deletions(-) diff --git a/src/base/base.cgh b/src/base/base.cgh index bd050b27..1ca2c53a 100644 --- a/src/base/base.cgh +++ b/src/base/base.cgh @@ -513,9 +513,12 @@ #if IsLanguageC #define Inf INFINITY #define Nan NAN - #define IsInf(x) isinf(x) - #define IsNan(x) isnan(x) +#elif IsLanguageG + #define Inf (1.0 / 0.0) + #define Nan (0.0 / 0.0) #endif +#define IsInf(x) isinf(x) +#define IsNan(x) isnan(x) //- u128 #if IsLanguageC diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index d82e0cfe..f8ac5a34 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -210,7 +210,6 @@ Rng2 S_BoundingBoxFromShape(S_Shape shape) return result; } - //////////////////////////////////////////////////////////// //~ Collision @@ -1078,6 +1077,7 @@ void S_TickForever(WaveLaneCtx *lane) ResetArena(world_arena); world = PushStruct(world_arena, S_World); + world->seed = tr.unpacked->seed; world->tick = tr.unpacked->tick; world->time_ns = tr.unpacked->time_ns; @@ -1399,8 +1399,40 @@ void S_TickForever(WaveLaneCtx *lane) + + + + + + + + + ////////////////////////////// - //- Check for bullet collisions + //- Spawn test bullet + + // TODO: Remove this + + // { + // b32 bullet_spawned = 0; + // for (S_Ent *ent = S_FirstEnt(world); ent->valid; ent = S_NextEnt(ent)) + // { + // if (ent->is_bullet) + // { + // bullet_spawned = 1; + // break; + // } + // } + + // if (!bullet_spawned) + // { + + // } + // } + + + ////////////////////////////// + //- Update bullets @@ -1571,6 +1603,7 @@ void S_TickForever(WaveLaneCtx *lane) SllQueuePush(output->first_snapshot_node, output->last_snapshot_node, snapshot_node); ++output->snapshots_count; + snapshot->seed = world->seed; snapshot->tick = world->tick; snapshot->time_ns = world->time_ns; diff --git a/src/pp/pp_sim/pp_sim_core.h b/src/pp/pp_sim/pp_sim_core.h index b794778b..a629f936 100644 --- a/src/pp/pp_sim/pp_sim_core.h +++ b/src/pp/pp_sim/pp_sim_core.h @@ -74,6 +74,10 @@ Struct(S_Ent) b32 has_weapon; + b32 is_bullet; + Vec2 bullet_start; + Vec2 bullet_end; + ////////////////////////////// //- Solver data @@ -158,6 +162,7 @@ Struct(S_Constraint) Struct(S_World) { + u64 seed; i64 tick; i64 time_ns; @@ -197,6 +202,7 @@ Struct(S_DeltaNode) Struct(S_Snapshot) { + u64 seed; i64 tick; i64 time_ns; diff --git a/src/pp/pp_sim/pp_sim_transcode.c b/src/pp/pp_sim/pp_sim_transcode.c index 69f4ff91..81a177fa 100644 --- a/src/pp/pp_sim/pp_sim_transcode.c +++ b/src/pp/pp_sim/pp_sim_transcode.c @@ -36,11 +36,13 @@ S_TranscodeResult S_TranscodeWorld(Arena *arena, S_World *src_world, String src_ if (pack) { + BB_WriteUBits(&bw, src_world->seed, 64); BB_WriteIBits(&bw, src_world->tick, 64); BB_WriteIBits(&bw, src_world->time_ns, 64); } else { + result.unpacked->seed = BB_ReadUBits(&br, 64); result.unpacked->tick = BB_ReadIBits(&br, 64); result.unpacked->time_ns = BB_ReadIBits(&br, 64); } @@ -138,6 +140,13 @@ S_TranscodeResult S_TranscodeWorld(Arena *arena, S_World *src_world, String src_ result.packed = BB_GetWritten(arena, &bw); BB_ReleaseDynamicBuff(&bb); } + else + { + if (!result.unpacked->seed) + { + TrueRand(StringFromStruct(&result.unpacked->seed)); + } + } } return result; diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index e408d477..83f1aa31 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -74,6 +74,7 @@ String V_StringFromHotkey(Arena *arena, V_Hotkey hotkey) V_Emitter *V_PushEmitter(u32 particle_count) { + particle_count = MinU32(particle_count, Mebi(1)); V_Frame *frame = V_CurrentFrame(); V_EmitterNode *en = PushStruct(frame->arena, V_EmitterNode); SllQueuePush(frame->first_emitter_node, frame->last_emitter_node, en); @@ -619,6 +620,7 @@ void V_TickForever(WaveLaneCtx *lane) S_Snapshot *snapshot = &n->snapshot; if (snapshot->tick > world->tick) { + world->seed = snapshot->seed; world->tick = snapshot->tick; world->time_ns = snapshot->time_ns; for (S_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next) @@ -2194,10 +2196,15 @@ void V_TickForever(WaveLaneCtx *lane) UI_PushCP(UI_BuildColumn()); { UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); - Vec2I32 tile_pos = S_TilePosFromWorldPos(frame->world_cursor); - Vec2 cell_pos = MulXformV2(frame->xf.world_to_cell, frame->world_cursor); - i32 tile_idx = S_TileIdxFromTilePos(tile_pos); { + UI_BuildLabelF("World seed: 0x%F", FmtHex(world->seed)); + } + UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); + { + UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); + Vec2I32 tile_pos = S_TilePosFromWorldPos(frame->world_cursor); + Vec2 cell_pos = MulXformV2(frame->xf.world_to_cell, frame->world_cursor); + i32 tile_idx = S_TileIdxFromTilePos(tile_pos); UI_BuildLabelF("Camera pos: %F", FmtFloat2(frame->camera_pos)); UI_BuildLabelF("Cursor world pos: %F", FmtFloat2(frame->world_cursor)); UI_BuildLabelF("Cursor tile pos: %F", FmtSint2(tile_pos)); @@ -2586,11 +2593,96 @@ void V_TickForever(WaveLaneCtx *lane) } UnlockTicketMutex(&S.input_back_tm); + + + + + + + + + ////////////////////////////// - //- Process bullets + //- Spawn test bullet particles // TODO: Not like this + { + PERSIST Vec2 start = {5, 5}; + PERSIST Vec2 end = {3, -20}; + + + if (frame->held_buttons[Button_G]) + { + end = frame->world_cursor; + if (!last_frame->held_buttons[Button_G]) + { + start = end; + } + } + + Vec2 vel = SubVec2(end, start); + + + f32 trail_len = Vec2Len(SubVec2(end, start)); + f32 particles_count = MaxF32(trail_len * 64, 1); + + + // f32 angle = AngleFromVec2(PerpVec2(SubVec2(end, start))); + f32 angle = AngleFromVec2(NegVec2(SubVec2(end, start))); + + V_Emitter *emitter = V_PushEmitter(particles_count); + + emitter->lifetime = 1; + emitter->lifetime_spread = 1; + + + emitter->angle = angle; + emitter->angle_spread = Tau / 4; + + emitter->start = start; + emitter->end = end; + + + emitter->color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1)); + + // emitter->speed = 0; + // emitter->speed_spread = 1; + + emitter->speed = 1; + emitter->speed_spread = 1; + + emitter->velocity_falloff = 0; + emitter->velocity_falloff_spread = 0; + + start = end; + end = AddVec2(end, vel); + } + + + + + + + + + + + + + + + + + + + + + + ////////////////////////////// + //- Spawn test blood particles + + // TODO: Not like this { for (S_Ent *firer = S_FirstEnt(world); firer->valid; firer = S_NextEnt(firer)) @@ -2634,23 +2726,22 @@ void V_TickForever(WaveLaneCtx *lane) { V_ParticleFlag flags = 0; flags |= V_ParticleFlag_StainOnPrune; - if (TweakBool("Emitter stain trail", 0)) + if (TweakBool("Emitter stain trail", 1)) { flags |= V_ParticleFlag_StainTrail; } // f32 count = TweakFloat("Emitter count", 50, 0, 10000); f32 count = TweakFloat("Emitter count", 50, 1, 1000); - f32 speed = TweakFloat("Emitter speed", 10, 0, 100); - f32 falloff = TweakFloat("Emitter falloff", 30, 0, 100); - // f32 angle_spread = TweakFloat("Emitter spread", Tau / 20, 0, Tau); - f32 angle_spread = TweakFloat("Emitter spread", 0.1, 0, 1) * Tau; + f32 speed = TweakFloat("Emitter speed", 20, 0, 100); + f32 falloff = TweakFloat("Emitter falloff", 50, 0, 100); + f32 angle_spread = TweakFloat("Emitter angle spread", 0.1, 0, 1) * Tau; V_Emitter *emitter = V_PushEmitter(count); emitter->flags = flags; Vec2 dir = victim_raycast.normal; - emitter->pos = victim_raycast.p; - + emitter->start = victim_raycast.p; + emitter->end = emitter->start; emitter->speed = speed; emitter->speed_spread = speed * 2; @@ -2696,7 +2787,8 @@ void V_TickForever(WaveLaneCtx *lane) V_Emitter *emitter = V_PushEmitter(25);; Vec2 dir = frame->look; - emitter->pos = frame->world_cursor; + emitter->start = frame->world_cursor; + emitter->end = emitter->start; emitter->angle = AngleFromVec2(dir); // emitter->count = 100; diff --git a/src/pp/pp_vis/pp_vis_gpu.g b/src/pp/pp_vis/pp_vis_gpu.g index b78e144c..084f97a0 100644 --- a/src/pp/pp_vis/pp_vis_gpu.g +++ b/src/pp/pp_vis/pp_vis_gpu.g @@ -291,34 +291,33 @@ ComputeShader(V_SimParticlesCS, 64) { V_Emitter emitter = G_Dereference(params.emitters)[particle.emitter_init_num - 1]; - u64 seed = MixU64(emitter.seed + particle.seq); + u64 seed0 = MixU64(emitter.seed + particle.seq); + u64 seed1 = MixU64(seed0); - // u32 speed_noise = (u32)((seed >> 0) & 0xFF); - // u32 angle_noise = (u32)((seed >> 8) & 0xFF); + f32 rand_speed = (f32)((seed0 >> 0) & 0xFFFF) / (f32)0xFFFF; + f32 rand_angle = (f32)((seed0 >> 16) & 0xFFFF) / (f32)0xFFFF; + f32 rand_offset = (f32)((seed0 >> 32) & 0xFFFF) / (f32)0xFFFF; + f32 rand_falloff = (f32)((seed0 >> 48) & 0xFFFF) / (f32)0xFFFF; - // u32 r_noise = (u32)((seed >> 8) & 0xFF); - // u32 g_noise = (u32)((seed >> 8) & 0xFF); - // u32 b_noise = (u32)((seed >> 8) & 0xFF); - // u32 a_noise = (u32)((seed >> 8) & 0xFF); + f32 rand_lifetime = (f32)((seed1 >> 0) & 0xFFFF) / (f32)0xFFFF; - // f32 speed_rand = speed_noise / (f32)0xFFFF; - // f32 angle_rand = angle_noise / (f32)0xFFFF; - - f32 rand_speed = (f32)((seed >> 0) & 0xFFFF) / (f32)0xFFFF - 0.5; - f32 rand_angle = (f32)((seed >> 16) & 0xFFFF) / (f32)0xFFFF - 0.5; - f32 rand_falloff = (f32)((seed >> 32) & 0xFFFF) / (f32)0xFFFF - 0.5; - f32 rand_color = (f32)((seed >> 48) & 0xFF) / (f32)0xFF - 0.5; - - f32 speed = emitter.speed + rand_speed * emitter.speed_spread; - f32 angle = emitter.angle + rand_angle * emitter.angle_spread; - f32 velocity_falloff = emitter.velocity_falloff + rand_falloff * emitter.velocity_falloff; - Vec3 color = emitter.color_lin.rgb + rand_color * emitter.color_spread; + f32 speed = emitter.speed + (rand_speed - 0.5) * emitter.speed_spread; + f32 angle = emitter.angle + (rand_angle - 0.5) * emitter.angle_spread; + f32 velocity_falloff = emitter.velocity_falloff + (rand_falloff - 0.5) * emitter.velocity_falloff_spread; + f32 lifetime = emitter.lifetime + (rand_lifetime - 0.5) * emitter.lifetime_spread; + Vec3 color = emitter.color_lin.rgb + (rand_lifetime - 0.5) * emitter.color_spread; + Vec2 offset = (emitter.end - emitter.start) * rand_offset; particle.flags = emitter.flags; - particle.pos = emitter.pos; + particle.pos = emitter.start + offset; particle.velocity = Vec2(cos(angle), sin(angle)) * speed; particle.velocity_falloff = velocity_falloff; particle.color = color; + particle.lifetime = lifetime; + if (emitter.lifetime == 0) + { + particle.lifetime = Inf; + } particle.emitter_init_num = 0; } @@ -327,7 +326,8 @@ ComputeShader(V_SimParticlesCS, 64) { particle.pos += particle.velocity * params.dt; particle.velocity = lerp(particle.velocity, 0, particle.velocity_falloff * params.dt); - if (particle.exists < 0.001 || dot(particle.velocity, particle.velocity) < (0.001 * 0.001)) + particle.lifetime -= params.dt; + if (particle.exists < 0.0001 || particle.lifetime < 0.0001 || dot(particle.velocity, particle.velocity) < (0.0001 * 0.0001)) { particle.exists = 0; } diff --git a/src/pp/pp_vis/pp_vis_shared.cgh b/src/pp/pp_vis/pp_vis_shared.cgh index e3a60912..7b4fe7dd 100644 --- a/src/pp/pp_vis/pp_vis_shared.cgh +++ b/src/pp/pp_vis/pp_vis_shared.cgh @@ -99,7 +99,11 @@ Struct(V_Emitter) u32 count; u64 seed; - Vec2 pos; + Vec2 start; + Vec2 end; + + f32 lifetime; + f32 lifetime_spread; f32 speed; f32 speed_spread; @@ -126,6 +130,7 @@ Struct(V_Particle) Vec2 velocity; f32 exists; + f32 lifetime; f32 velocity_falloff; Vec3 color;