working guy anim

This commit is contained in:
jacob 2026-01-30 07:31:57 -06:00
parent b7e2fafc85
commit 253670856a
10 changed files with 148 additions and 81 deletions

View File

@ -463,7 +463,7 @@ ASE_Meta ASE_DecodeMeta(Arena *arena, String encoded)
chunk->kind = ASE_ChunkKind_Tag;
chunk->tag.from = BB_ReadUBits(&bbr, 16);
chunk->tag.to = BB_ReadUBits(&bbr, 16);
chunk->tag.to = BB_ReadUBits(&bbr, 16) + 1;
BB_ReadSeekBytes(&bbr, 13);
chunk->name.len = BB_ReadUBits(&bbr, 16);
@ -628,6 +628,7 @@ ASE_Meta ASE_DecodeMeta(Arena *arena, String encoded)
span->name = chunk->name;
span->from = chunk->tag.from;
span->to = chunk->tag.to;
++spans_count;
}
}
}

View File

@ -526,14 +526,14 @@ i32 WindingFromVec2(Vec2 a, Vec2 b)
return (w >= 0) - (w < 0);
}
Vec2 RotateVec2(Vec2 v, f32 a)
Vec2 RotateVec2Angle(Vec2 v, f32 a)
{
f32 c = CosF32(a);
f32 s = SinF32(a);
return VEC2(v.x * c - v.y * s, v.x * s + v.y * c);
}
Vec2 RotateVec2Vec2(Vec2 a, Vec2 b)
Vec2 RotateVec2(Vec2 a, Vec2 b)
{
return VEC2(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
}
@ -832,6 +832,7 @@ b32 MatchAffine(Affine af0, Affine af1)
}
//- Initialization
Affine AffineFromPos(Vec2 v)
{
Affine af;
@ -841,7 +842,16 @@ Affine AffineFromPos(Vec2 v)
return af;
}
Affine AffineFromRot(f32 r)
Affine AffineFromRot(Vec2 r)
{
Affine result;
result.bx = VEC2(r.x, r.y);
result.by = VEC2(-r.y, r.x);
result.og = VEC2(0, 0);
return result;
}
Affine AffineFromAngle(f32 r)
{
Affine result;
f32 c = CosF32(r);
@ -862,6 +872,7 @@ Affine AffineFromScale(Vec2 scale)
}
//- Translation
Affine TranslateAffine(Affine af, Vec2 v)
{
af.og = VEC2(af.bx.x * v.x + af.by.x * v.y + af.og.x, af.bx.y * v.x + af.by.y * v.y + af.og.y);
@ -875,17 +886,23 @@ Affine WorldTranslateAffine(Affine af, Vec2 v)
}
//- Rotation
Affine RotateAffine(Affine af, f32 r)
Affine RotateAffine(Affine af, Vec2 r)
{
return MulAffine(af, AffineFromRot(r));
}
Affine WorldRotateAffine(Affine af, f32 r)
Affine RotateAffineAngle(Affine af, f32 r)
{
return MulAffine(AffineFromRot(r), af);
return MulAffine(af, AffineFromAngle(r));
}
Affine WorldRotateAffineBasis(Affine af, f32 r)
Affine WorldRotateAffineAngle(Affine af, f32 r)
{
return MulAffine(AffineFromAngle(r), af);
}
Affine WorldRotateAffineBasisAngle(Affine af, f32 r)
{
f32 diff = r;
f32 c = CosF32(diff);
@ -895,12 +912,13 @@ Affine WorldRotateAffineBasis(Affine af, f32 r)
return af;
}
Affine AffineWithWorldRotation(Affine af, f32 r)
Affine AffineWithWorldRotationAngle(Affine af, f32 r)
{
return WorldRotateAffineBasis(af, r - RotationFromAffine(af));
return WorldRotateAffineBasisAngle(af, r - AngleFromAffine(af));
}
//- Scale
Affine ScaleAffine(Affine af, Vec2 scale)
{
af.bx = MulVec2(af.bx, scale.x);
@ -918,6 +936,7 @@ Affine WorldScaleAffine(Affine af, Vec2 scale)
}
//- Lerp
Affine LerpAffine(Affine a, Affine b, f32 t)
{
Affine result;
@ -928,6 +947,7 @@ Affine LerpAffine(Affine a, Affine b, f32 t)
}
//- Invert
Affine InvertAffine(Affine af)
{
f32 det = DeterminantFromAffine(af);
@ -946,6 +966,7 @@ Affine InvertAffine(Affine af)
}
//- Mul
Affine MulAffine(Affine a, Affine b)
{
Affine result;
@ -988,6 +1009,25 @@ Vec2 InvertAffineMulVec2(Affine af, Vec2 v)
}
//- Helpers
Affine AffineFromXform(Xform xf)
{
Affine result = Zi;
Vec2 rot = xf.r;
if (rot.x == 0 && rot.y == 0)
{
rot.x = 1;
}
else
{
rot = NormVec2(rot);
}
result.bx = rot;
result.by = PerpVec2(rot);
result.og = xf.t;
return result;
}
Affine BasisFromAffine(Affine af)
{
Affine result = Zi;
@ -1021,7 +1061,7 @@ Vec2 DownFromAffine(Affine af)
return af.by;
}
f32 RotationFromAffine(Affine af)
f32 AngleFromAffine(Affine af)
{
return AngleFromVec2(af.bx);
}
@ -1036,18 +1076,38 @@ Vec2 ScaleFromAffine(Affine af)
////////////////////////////////////////////////////////////
//~ Xform
Xform NormXform(Xform xf)
{
if (xf.r.x == 0 && xf.r.y == 0)
{
xf.r.x = 1;
}
else
{
xf.r = NormVec2(xf.r);
}
return xf;
}
Xform InvertXform(Xform xf)
{
xf.t = NegVec2(xf.t);
xf.r = NegVec2(xf.r);
return xf;
}
Xform MulXform(Xform a, Xform b)
{
Xform result = Zi;
result.r = RotateVec2Vec2(a.r, b.r);
result.t = AddVec2(RotateVec2Vec2(a.r, b.t), a.t);
result.r = RotateVec2(a.r, b.r);
result.t = AddVec2(RotateVec2(a.r, b.t), a.t);
return result;
}
Vec2 MulXformVec2(Xform xf, Vec2 v)
{
Vec2 result = Zi;
result = AddVec2(RotateVec2Vec2(v, xf.r), xf.t);
result = AddVec2(RotateVec2(v, xf.r), xf.t);
return result;
}

View File

@ -387,8 +387,8 @@ Vec2 CeilVec2(Vec2 a);
//- Angle
i32 WindingFromVec2(Vec2 a, Vec2 b);
Vec2 RotateVec2(Vec2 v, f32 a);
Vec2 RotateVec2Vec2(Vec2 a, Vec2 b);
Vec2 RotateVec2Angle(Vec2 v, f32 a);
Vec2 RotateVec2(Vec2 a, Vec2 b);
Vec2 Vec2FromAngle(f32 a);
f32 AngleFromVec2(Vec2 v);
@ -463,7 +463,8 @@ b32 MatchAffine(Affine af0, Affine af1);
//- Initialization
Affine AffineFromPos(Vec2 v);
Affine AffineFromRot(f32 r);
Affine AffineFromRot(Vec2 r);
Affine AffineFromAngle(f32 r);
Affine AffineFromScale(Vec2 scale);
//- Translation
@ -471,10 +472,11 @@ Affine TranslateAffine(Affine af, Vec2 v);
Affine WorldTranslateAffine(Affine af, Vec2 v);
//- Rotation
Affine RotateAffine(Affine af, f32 r);
Affine WorldRotateAffine(Affine af, f32 r);
Affine WorldRotateAffineBasis(Affine af, f32 r);
Affine AffineWithWorldRotation(Affine af, f32 r);
Affine RotateAffine(Affine af, Vec2 r);
Affine RotateAffineAngle(Affine af, f32 r);
Affine WorldRotateAffineAngle(Affine af, f32 r);
Affine WorldRotateAffineBasisAngle(Affine af, f32 r);
Affine AffineWithWorldRotationAngle(Affine af, f32 r);
//- Scale
Affine ScaleAffine(Affine af, Vec2 scale);
@ -494,13 +496,14 @@ Vec2 InvertAffineMulVec2(Affine af, Vec2 v);
Vec2 InvertAffineBasisMulVec2(Affine af, Vec2 v);
//- Helpers
Affine AffineFromXform(Xform xf);
Affine BasisFromAffine(Affine af);
f32 DeterminantFromAffine(Affine af);
Vec2 RightFromAffine(Affine af);
Vec2 LeftFromAffine(Affine af);
Vec2 UpFromAffine(Affine af);
Vec2 DownFromAffine(Affine af);
f32 RotationFromAffine(Affine af);
f32 AngleFromAffine(Affine af);
Vec2 ScaleFromAffine(Affine af);
////////////////////////////////////////////////////////////
@ -509,6 +512,8 @@ Vec2 ScaleFromAffine(Affine af);
#define XformIdentity ((Xform) { .r = { 1, 0 } })
#define CompXformIdentity { .r = { 1, 0 } }
Xform NormXform(Xform xf);
Xform InvertXform(Xform xf);
Vec2 MulXformVec2(Xform xf, Vec2 v);
////////////////////////////////////////////////////////////

View File

@ -2,6 +2,7 @@ P_Ctx P = Zi;
ThreadLocal P_ThreadLocalCtx P_tl = Zi;
Readonly P_Ent P_NilEnt = {
.prev_xf = CompXformIdentity,
.xf = CompXformIdentity,
.control.look = { 1, 0 },
};
@ -1455,6 +1456,8 @@ void P_SpawnEntsFromList(P_Frame *frame, P_EntList ents)
P_Ent *old_prev_in_bin = dst->prev_in_bin;
{
*dst = *src;
dst->prev_xf = NormXform(dst->prev_xf);
dst->xf = NormXform(dst->xf);
}
dst->next = old_next;
dst->prev = old_prev;
@ -2405,7 +2408,7 @@ void P_StepFrame(P_Frame *frame)
{
Xform xf = ent->xf;
xf.t = AddVec2(xf.t, MulVec2(ent->solved_v, solver_dt));
xf.r = RotateVec2(xf.r, ent->solved_w * solver_dt);
xf.r = RotateVec2Angle(xf.r, ent->solved_w * solver_dt);
ent->xf = xf;
}
}

BIN
src/pp/pp_res/sprite/bla3.ase (Stored with Git LFS)

Binary file not shown.

View File

@ -617,15 +617,6 @@ void S_TickForever(WaveLaneCtx *lane)
dummy->exists = 1;
dummy->guy = guy->key;
P_SetEntString(dummy, Lit("Dummy"));
// P_Ent *ent = P_PushTempEnt(frame_arena, &ents);
// *ent = P_NilEnt;
// ent->key = msg->key;
// ent->xf = msg->xf;
// ent->is_guy = 1;
// ent->is_dummy = 1;
// ent->has_weapon = 1;
// ent->exists = 1;
}
P_SpawnEntsFromList(world_frame, ents);
} break;

View File

@ -959,7 +959,7 @@ void V_TickForever(WaveLaneCtx *lane)
frame->shade_cursor = MulAffineVec2(frame->af.screen_to_shade, frame->screen_cursor);
frame->world_cursor = MulAffineVec2(frame->af.screen_to_world, frame->screen_cursor);
b32 show_editor_ui = TweakBool("Show editor UI", 1);
b32 show_editor_ui = TweakBool("Show editor UI", 0);
frame->world_selection_start = frame->world_cursor;
if (frame->is_editing)
@ -1834,50 +1834,57 @@ void V_TickForever(WaveLaneCtx *lane)
//////////////////////////////
//- Push guy quads
// for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
// {
// if (ent->is_guy)
// {
// P_Anim anim = P_AnimFromEnt(ent, local_frame->time_ns);
for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
{
if (ent->is_guy)
{
P_Anim anim = P_AnimFromEnt(ent, local_frame->time_ns);
// SPR_Slice body_slice = SPR_SliceFromSheet(anim.sheet, anim.span, anim.frame_seq);
// if (body_slice.ready)
// {
// Affine body_to_world_af = AffineIdentity;
// {
// // FIXME: Use origin ray
// Vec2 world_dims = DivVec2(body_slice.dims, P_CellsPerMeter);
// body_to_world_af.og = ent->af.og;
// // body_to_world_af.og = SubVec2(body_to_world_af.og, MulVec2(world_dims, 0.25));
// body_to_world_af = AffineWithWorldRotation(body_to_world_af, AngleFromVec2(ent->control.look));
// body_to_world_af = TranslateAffine(body_to_world_af, MulVec2(world_dims, -0.5));
// body_to_world_af = ScaleAffine(body_to_world_af, world_dims);
// }
// // Push body quad
// {
// V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
// quad->to_shade_af = MulAffine(frame->af.world_to_shade, body_to_world_af);
// quad->tex = body_slice.tex;
// quad->uv_rect = body_slice.uv_rect;
// }
// }
SPR_Slice body_slice = SPR_SliceFromSheet(anim.sheet, anim.span, anim.frame_seq);
// // SPR_Slice wep_slice = SPR_FrameFromSheet(anim.weapon_sheet, anim.span, anim.frame_seq);
// // Affine wep_to_world_af = AffineIdentity;
// // {
// // }
// // // Push weapon quad
// // {
// // V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
// // quad->af = MulAffine(frame->af.world_to_shade, wep_to_world_af);
// // quad->slice = wep_sframe.slice;
// // }
// }
// }
if (body_slice.ready)
{
Affine body_to_world_af = AffineIdentity;
{
Vec2 pix_dims = DimsFromRng2(body_slice.bounds);
Vec2 world_dims = DivVec2(pix_dims, P_CellsPerMeter);
Xform origin_ray = body_slice.rays[SPR_RayKind_Origin];
origin_ray.t = SubVec2(origin_ray.t, body_slice.bounds.p0);
origin_ray = InvertXform(origin_ray);
Affine origin_to_body_af = AffineIdentity;
origin_to_body_af = ScaleAffine(origin_to_body_af, DivVec2Vec2(VEC2(1.0, 1.0), pix_dims));
origin_to_body_af = RotateAffine(origin_to_body_af, origin_ray.r);
origin_to_body_af = TranslateAffine(origin_to_body_af, origin_ray.t);
origin_to_body_af = ScaleAffine(origin_to_body_af, pix_dims);
Affine body_to_ent_af = AffineIdentity;
body_to_ent_af = ScaleAffine(body_to_ent_af, world_dims);
body_to_ent_af = MulAffine(body_to_ent_af, origin_to_body_af);
Xform ent_xf = ent->xf;
// FIXME: Remove this
ent_xf.r = ent->control.look;
body_to_world_af = MulAffine(AffineFromXform(ent_xf), body_to_ent_af);
}
// Push body quad
{
V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
quad->to_shade_af = MulAffine(frame->af.world_to_shade, body_to_world_af);
quad->tex = body_slice.tex;
quad->tex_rect_uv = body_slice.tex_rect_uv;
}
}
}
}

View File

@ -91,7 +91,7 @@ VertexShader(V_QuadVS, V_QuadPSInput)
Vec2 rect_uv = RectUvFromIdx(SV_VertexID);
Vec2 shade_pos = mul(quad.to_shade_af, Vec3(rect_uv, 1));
Vec2 tex_uv = lerp(quad.uv_rect.p0, quad.uv_rect.p1, rect_uv);
Vec2 tex_uv = lerp(quad.tex_rect_uv.p0, quad.tex_rect_uv.p1, rect_uv);
// Vec2 shade_pos = lerp(quad.p0, quad.p1, rect_uv);
V_QuadPSInput result;
@ -112,10 +112,10 @@ PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
V_Quad quad = quads[input.quad_idx];
// Texture2D<Vec4> tex = G_Dereference<Vec4>(quad.tex);
// Vec4 albedo = tex.Sample(clamp_sampler, input.tex_uv);
Texture2D<Vec4> tex = G_Dereference<Vec4>(quad.tex);
Vec4 albedo = tex.Sample(clamp_sampler, input.tex_uv);
Vec4 albedo = Color_Cyan;
// Vec4 albedo = Color_Cyan;
V_QuadPSOutput output;
output.sv_target0 = albedo;

View File

@ -185,7 +185,7 @@ Struct(V_Quad)
V_QuadFlag flags;
Affine to_shade_af;
G_Texture2DRef tex;
Rng2 uv_rect;
Rng2 tex_rect_uv;
};
////////////////////////////////////////////////////////////

View File

@ -383,7 +383,7 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
//- Composite
ASE_Image composite = ASE_PushBlankImage(frame_arena, slice->bounds);
for (ASE_Layer *ase_layer = sheet->meta.last_layer; ase_layer; ase_layer = ase_layer->prev)
for (ASE_Layer *ase_layer = sheet->meta.first_layer; ase_layer; ase_layer = ase_layer->next)
{
SPR_LayerKind kind = SPR_LayerKindFromName(ase_layer->name);
if (kind == SPR_LayerKind_Visual)