working weapon animation

This commit is contained in:
jacob 2026-01-31 14:18:40 -06:00
parent 4e96e2f4d5
commit a99ae88d22
8 changed files with 107 additions and 65 deletions

View File

@ -543,6 +543,12 @@ Vec2 RotateVec2(Vec2 a, Vec2 b)
return VEC2(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
}
Vec2 InvertRot(Vec2 r)
{
r.y = -r.y;
return r;
}
Vec2 Vec2FromAngle(f32 a)
{
return VEC2(CosF32(a), SinF32(a));
@ -897,21 +903,11 @@ Affine RotateAffine(Affine af, Vec2 r)
return MulAffine(af, AffineFromRot(r));
}
Affine RotateAffineAngle(Affine af, f32 r)
{
return MulAffine(af, AffineFromAngle(r));
}
Affine PreRotateAffine(Affine af, Vec2 r)
{
return MulAffine(AffineFromRot(r), af);
}
Affine PreRotateAffineAngle(Affine af, f32 r)
{
return MulAffine(AffineFromAngle(r), af);
}
//- Scale
Affine ScaleAffine(Affine af, Vec2 scale)
@ -988,18 +984,15 @@ Vec2 MulAffineVec2(Affine af, Vec2 v)
return result;
}
Affine MulAffineXformTR(Affine af, Xform xf)
Affine MulAffineXform(Affine af, Xform xf)
{
af = TranslateAffine(af, xf.t);
af = RotateAffine(af, xf.r);
return af;
}
Affine MulAffineXformRT(Affine af, Xform xf)
{
af = RotateAffine(af, xf.r);
af = TranslateAffine(af, xf.t);
return af;
Affine result;
result.bx.x = af.bx.x * xf.r.x + af.by.x * xf.r.y;
result.bx.y = af.bx.y * xf.r.x + af.by.y * xf.r.y;
result.by.x = af.bx.x * -xf.r.y + af.by.x * xf.r.x;
result.by.y = af.bx.y * -xf.r.y + af.by.y * xf.r.x;
result.og = MulAffineVec2(af, xf.t);
return result;
}
//- Helpers
@ -1060,9 +1053,26 @@ Xform MakeXform(Vec2 t, Vec2 r)
return xf;
}
Xform NormXform(Xform xf)
Xform MulXform(Xform a, Xform b)
{
xf.r = NormRot(xf.r);
Xform result;
result.r.x = a.r.x * b.r.x + -a.r.y * b.r.y;
result.r.y = a.r.y * b.r.x + a.r.x * b.r.y;
result.t.x = a.r.x * b.t.x + -a.r.y * b.t.y;
result.t.y = a.r.y * b.t.x + a.r.x * b.t.y;
result.t = AddVec2(result.t, a.t);
return result;
}
Xform TranslateXform(Xform xf, Vec2 t)
{
xf.t = VEC2(xf.r.x * t.x + -xf.r.y * t.y + xf.t.x, xf.r.y * t.x + xf.r.x * t.y + xf.t.y);
return xf;
}
Xform RotateXform(Xform xf, Vec2 r)
{
xf.r = RotateVec2(xf.r, r);
return xf;
}
@ -1073,14 +1083,6 @@ Xform InvertXform(Xform xf)
return xf;
}
Xform MulXform(Xform a, Xform b)
{
Xform result = Zi;
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;
@ -1088,6 +1090,12 @@ Vec2 MulXformVec2(Xform xf, Vec2 v)
return result;
}
Xform NormXform(Xform xf)
{
xf.r = NormRot(xf.r);
return xf;
}
Vec2 NormRot(Vec2 r)
{
if (r.x == 0 && r.y == 0)

View File

@ -390,6 +390,7 @@ Vec2 CeilVec2(Vec2 a);
i32 WindingFromVec2(Vec2 a, Vec2 b);
Vec2 RotateVec2Angle(Vec2 v, f32 a);
Vec2 RotateVec2(Vec2 a, Vec2 b);
Vec2 InvertRot(Vec2 r);
Vec2 Vec2FromAngle(f32 a);
f32 AngleFromVec2(Vec2 v);
@ -474,9 +475,7 @@ Affine PreTranslateAffine(Affine af, Vec2 v);
//- Rotation
Affine RotateAffine(Affine af, Vec2 r);
Affine RotateAffineAngle(Affine af, f32 r);
Affine PreRotateAffine(Affine af, Vec2 r);
Affine PreRotateAffineAngle(Affine af, f32 r);
//- Scale
Affine ScaleAffine(Affine af, Vec2 scale);
@ -492,8 +491,6 @@ Affine InvertAffine(Affine af);
Affine MulAffine(Affine a, Affine b);
Vec2 MulAffineVec2(Affine af, Vec2 v);
Vec2 MulAffineBasisVec2(Affine af, Vec2 v);
Affine MulAffineXformTR(Affine af, Xform xf);
Affine MulAffineXformRT(Affine af, Xform xf);
//- Helpers
Affine BasisFromAffine(Affine af);
@ -513,10 +510,14 @@ Vec2 ScaleFromAffine(Affine af);
Xform MakeXform(Vec2 t, Vec2 r);
Xform NormXform(Xform xf);
Xform MulXform(Xform a, Xform b);
Xform TranslateXform(Xform xf, Vec2 t);
Xform RotateXform(Xform xf, Vec2 r);
Xform InvertXform(Xform xf);
Vec2 MulXformVec2(Xform xf, Vec2 v);
Xform NormXform(Xform xf);
Vec2 NormRot(Vec2 r);
////////////////////////////////////////////////////////////

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

View File

@ -1848,24 +1848,52 @@ void V_TickForever(WaveLaneCtx *lane)
// FIXME: Remove this
Xform ent_to_world_xf = ent->xf;
ent_to_world_xf = MakeXform(ent->xf.t, ent->control.look);
Affine ent_to_world_af = MulAffineXformTR(AffineIdentity, ent_to_world_xf);
Affine ent_to_world_af = MulAffineXform(AffineIdentity, ent_to_world_xf);
//- Compute body
SPR_Slice body = SPR_SliceFromSheet(anim.sheet, anim.span, anim.frame_seq);
Affine body_to_world_af = ent_to_world_af;
SPR_Slice wep = SPR_SliceFromSheet(anim.wep_sheet, anim.span, anim.frame_seq);
Affine body_pix_to_world_af = AffineIdentity;
{
Xform anchor_to_body_xf = InvertXform(body.rays[SPR_RayKind_Anchor]);
body_to_world_af = ScaleAffine(body_to_world_af, pix_scale);
body_to_world_af = RotateAffine(body_to_world_af, anchor_to_body_xf.r);
body_to_world_af = TranslateAffine(body_to_world_af, anchor_to_body_xf.t);
body_pix_to_world_af = MulAffine(body_pix_to_world_af, ent_to_world_af);
body_pix_to_world_af = ScaleAffine(body_pix_to_world_af, pix_scale);
SPR_Ray anchor_ray = body.rays[SPR_RayKind_Anchor];
body_pix_to_world_af = RotateAffine(body_pix_to_world_af, InvertRot(anchor_ray.dir));
body_pix_to_world_af = TranslateAffine(body_pix_to_world_af, NegVec2(anchor_ray.pos));
}
Affine wep_pix_to_world_af = AffineIdentity;
{
wep_pix_to_world_af = MulAffine(wep_pix_to_world_af, ent_to_world_af);
wep_pix_to_world_af = ScaleAffine(wep_pix_to_world_af, pix_scale);
SPR_Ray body_anchor_ray = body.rays[SPR_RayKind_Anchor];
SPR_Ray body_ap_ray = body.rays[SPR_RayKind_Ap];
wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, InvertRot(body_anchor_ray.dir));
wep_pix_to_world_af = TranslateAffine(wep_pix_to_world_af, SubVec2(body_ap_ray.pos, body_anchor_ray.pos));
wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, InvertRot(body_ap_ray.dir));
SPR_Ray anchor_ray = wep.rays[SPR_RayKind_Anchor];
wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, anchor_ray.dir);
wep_pix_to_world_af = TranslateAffine(wep_pix_to_world_af, NegVec2(anchor_ray.pos));
}
//- Push weapon quad
if (body.ready && wep.ready)
{
Affine wep_uv_to_world_af = ScaleAffine(wep_pix_to_world_af, DimsFromRng2(wep.tex_rect));
V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
quad->quad_uv_to_shade_af = MulAffine(frame->af.world_to_shade, wep_uv_to_world_af);
quad->tex = wep.tex;
quad->tex_slice_uv = DivRng2Vec2(wep.tex_rect, wep.tex_dims);
}
//- Push body quad
if (body.ready)
{
Affine body_uv_to_world_af = ScaleAffine(body_to_world_af, DimsFromRng2(body.tex_rect));
Affine body_uv_to_world_af = ScaleAffine(body_pix_to_world_af, DimsFromRng2(body.tex_rect));
V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
quad->quad_uv_to_shade_af = MulAffine(frame->af.world_to_shade, body_uv_to_world_af);
@ -1874,7 +1902,6 @@ void V_TickForever(WaveLaneCtx *lane)
}
}
}
}

View File

@ -113,7 +113,7 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f
Atomic64Set(&slice->atlas_copy_completion_target, I64Max);
for (SPR_RayKind ray_kind = 0; ray_kind < SPR_RayKind_COUNT; ++ray_kind)
{
slice->rays[ray_kind] = XformIdentity;
slice->rays[ray_kind].dir.x = 1;
}
}
@ -192,11 +192,11 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f
if (alpha > 0)
{
// TODO: Different quantization so that 128 equals 0, instead of approximately 0
f32 rot_x = (((f32)((ray_pix >> 0) & 0xFF) / 255.0) * 2.0) - 1;
f32 rot_y = (((f32)((ray_pix >> 8) & 0xFF) / 255.0) * 2.0) - 1;
Vec2 rot = NormVec2(VEC2(rot_x, rot_y));
slice->rays[ray_kind].r = rot;
slice->rays[ray_kind].t = SubVec2(ase_cel->bounds.p0, slice->canvas_rect.p0);
f32 dir_x = (((f32)((ray_pix >> 0) & 0xFF) / 255.0) * 2.0) - 1;
f32 dir_y = (((f32)((ray_pix >> 8) & 0xFF) / 255.0) * 2.0) - 1;
Vec2 dir = NormVec2(VEC2(dir_x, dir_y));
slice->rays[ray_kind].pos = SubVec2(ase_cel->bounds.p0, slice->canvas_rect.p0);
slice->rays[ray_kind].dir = dir;
}
}
}

View File

@ -49,9 +49,15 @@ Enum(SPR_LayerKind)
////////////////////////////////////////////////////////////
//~ Lookup result types
Struct(SPR_Ray)
{
Vec2 pos;
Vec2 dir;
};
Struct(SPR_Slice)
{
Xform rays[SPR_RayKind_COUNT];
SPR_Ray rays[SPR_RayKind_COUNT];
Vec2 tex_dims;
G_Texture2DRef tex;
@ -71,7 +77,7 @@ Struct(SPR_SliceEntry)
SPR_SliceEntry *next_in_bin;
Rng2 canvas_rect;
Xform rays[SPR_RayKind_COUNT];
SPR_Ray rays[SPR_RayKind_COUNT];
Atomic64 atlas_copy_completion_target;
SPR_Atlas *atlas;