Skip to content

Commit

Permalink
Move skeleton building and blending to engine
Browse files Browse the repository at this point in the history
  • Loading branch information
VReaperV committed Jan 7, 2025
1 parent 782d78f commit cf47328
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 7 deletions.
26 changes: 22 additions & 4 deletions src/engine/client/cg_msgdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,36 @@ namespace Util {
}
};

template<> struct SerializeTraits<std::vector<BoneMod>> {
static void Write( Writer& stream, const std::vector<BoneMod>& boneMods ) {
stream.WriteSize( boneMods.size() );
stream.WriteData( boneMods.data(), boneMods.size() * sizeof( BoneMod ) );
}

static std::vector<BoneMod> Read( Reader& stream ) {
std::vector<BoneMod> boneMods;
const size_t size = stream.ReadSize<BoneMod>();
boneMods.resize( size );
stream.ReadData( boneMods.data(), size * sizeof( BoneMod ) );
return boneMods;
}
};

// Use that bone optimization for refEntity_t
template<> struct SerializeTraits<refEntity_t> {
static void Write(Writer& stream, const refEntity_t& ent)
{
stream.WriteData(&ent, offsetof(refEntity_t, skeleton));
stream.Write<refSkeleton_t>(ent.skeleton);
stream.WriteData(&ent, offsetof(refEntity_t, boneMods));
stream.Write<std::vector<BoneMod>>( ent.boneMods );
// stream.Write<refSkeleton_t>(ent.skeleton);
}

static refEntity_t Read(Reader& stream)
{
refEntity_t ent;
stream.ReadData(&ent, offsetof(refEntity_t, skeleton));
ent.skeleton = stream.Read<refSkeleton_t>();
stream.ReadData(&ent, offsetof(refEntity_t, boneMods));
ent.boneMods = stream.Read<std::vector<BoneMod>>();
// ent.skeleton = stream.Read<refSkeleton_t>();
return ent;
}
};
Expand Down
27 changes: 27 additions & 0 deletions src/engine/renderer/tr_animation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1313,6 +1313,32 @@ static int IQMBuildSkeleton( refSkeleton_t *skel, skelAnimation_t *skelAnim,
return true;
}

void R_TransformSkeleton( refSkeleton_t* skel, const float scale ) {
skel->scale = scale;

switch ( skel->type ) {
case refSkeletonType_t::SK_INVALID:
case refSkeletonType_t::SK_ABSOLUTE:
return;

default:
break;
}

// calculate absolute transforms
for ( refBone_t* bone = &skel->bones[0]; bone < &skel->bones[skel->numBones]; bone++ ) {
if ( bone->parentIndex >= 0 ) {
refBone_t* parent;

parent = &skel->bones[bone->parentIndex];

TransCombine( &bone->t, &parent->t, &bone->t );
}
}

skel->type = refSkeletonType_t::SK_ABSOLUTE;
}

/*
==============
RE_BuildSkeleton
Expand Down Expand Up @@ -1468,6 +1494,7 @@ int RE_BuildSkeleton( refSkeleton_t *skel, qhandle_t hAnim, int startFrame, int
}

// FIXME: clear existing bones and bounds?
skel->numBones = 0;
return false;
}

Expand Down
1 change: 1 addition & 0 deletions src/engine/renderer/tr_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -3730,6 +3730,7 @@ inline bool checkGLErrors()
int RE_CheckSkeleton( refSkeleton_t *skel, qhandle_t hModel, qhandle_t hAnim );
int RE_BuildSkeleton( refSkeleton_t *skel, qhandle_t anim, int startFrame, int endFrame, float frac,
bool clearOrigin );
void R_TransformSkeleton( refSkeleton_t* skel, const float scale );
int RE_BlendSkeleton( refSkeleton_t *skel, const refSkeleton_t *blend, float frac );
int RE_AnimNumFrames( qhandle_t hAnim );
int RE_AnimFrameRate( qhandle_t hAnim );
Expand Down
59 changes: 57 additions & 2 deletions src/engine/renderer/tr_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2095,19 +2095,74 @@ void R_AddEntitySurfaces()
}
else
{
switch ( tr.currentModel->type )
{
switch ( tr.currentModel->type ) {
case modtype_t::MOD_MESH:
R_AddMDVSurfaces( ent );
break;

case modtype_t::MOD_MD5:
/* Log::Warn("%i %s: old: %i-%i %f new: %i-%i %f | %f %f", ent->e.animationHandle,
R_GetAnimationByHandle( ent->e.animationHandle )->name, ent->e.startFrame,
ent->e.endFrame, ent->e.lerp, ent->e.startFrame2, ent->e.endFrame2, ent->e.lerp2,
ent->e.blendLerp, ent->e.scale ); */
if ( ent->e.scale == 0 ) {
ent->e.scale = 1;
}
if ( ent->e.animationHandle == 0 ) {
ent->e.animationHandle = ent->e.animationHandle2;
} else if ( ent->e.animationHandle2 == 0 ) {
ent->e.animationHandle2 = ent->e.animationHandle;
}

RE_BuildSkeleton( &ent->e.skeleton, ent->e.animationHandle, ent->e.startFrame, ent->e.endFrame,
ent->e.lerp, ent->e.clearOrigin );
ent->e.skeleton.scale = ent->e.scale;
if ( ent->e.blendLerp > 0.0 ) {
refSkeleton_t skel;
RE_BuildSkeleton( &skel, ent->e.animationHandle2, ent->e.startFrame2, ent->e.endFrame2,
ent->e.lerp2, ent->e.clearOrigin2 );
RE_BlendSkeleton( &ent->e.skeleton, &skel, ent->e.blendLerp );
}

for ( const BoneMod& boneMod : ent->e.boneMods ) {
QuatMultiply2( ent->e.skeleton.bones[boneMod.index].t.rot, boneMod.rotation );
}
R_AddMD5Surfaces( ent );
break;

case modtype_t::MOD_IQM:
{
/* Log::Warn("%i %s: old: %i-%i %f new: %i-%i %f | %f %f", ent->e.animationHandle,
R_GetAnimationByHandle( ent->e.animationHandle )->name, ent->e.startFrame,
ent->e.endFrame, ent->e.lerp, ent->e.startFrame2, ent->e.endFrame2, ent->e.lerp2,
ent->e.blendLerp, ent->e.scale ); */
bool transform = true;
if ( ent->e.scale == 0 ) {
ent->e.scale = 1;
}
if ( ent->e.animationHandle == 0 ) {
ent->e.animationHandle = ent->e.animationHandle2;
} else if ( ent->e.animationHandle2 == 0 ) {
ent->e.animationHandle2 = ent->e.animationHandle;
}

ent->e.skeleton.scale = ent->e.scale;
RE_BuildSkeleton( &ent->e.skeleton, ent->e.animationHandle, ent->e.startFrame, ent->e.endFrame,
ent->e.lerp, ent->e.clearOrigin );
if ( ent->e.blendLerp > 0.0 ) {
refSkeleton_t skel;
RE_BuildSkeleton( &skel, ent->e.animationHandle2, ent->e.startFrame2, ent->e.endFrame2,
ent->e.lerp2, ent->e.clearOrigin2 );
RE_BlendSkeleton( &ent->e.skeleton, &skel, ent->e.blendLerp );
}

for ( const BoneMod& boneMod : ent->e.boneMods ) {
QuatMultiply2( ent->e.skeleton.bones[boneMod.index].t.rot, boneMod.rotation );
}
R_TransformSkeleton( &ent->e.skeleton, ent->e.scale );
R_AddIQMSurfaces( ent );
break;
}

case modtype_t::MOD_BSP:
R_AddBSPModelSurfaces( ent );
Expand Down
21 changes: 21 additions & 0 deletions src/engine/renderer/tr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ enum class refSkeletonType_t
SK_ABSOLUTE
};

struct BoneMod {
int index;
vec3_t translation;
quat_t rotation;
};

struct alignas(16) refSkeleton_t
{
refSkeletonType_t type; // skeleton has been reset
Expand Down Expand Up @@ -211,6 +217,21 @@ struct refEntity_t

int altShaderIndex;

qhandle_t animationHandle;
int startFrame;
int endFrame;
float lerp;
int clearOrigin;
qhandle_t animationHandle2;
int startFrame2;
int endFrame2;
float lerp2;
int clearOrigin2;
float blendLerp;
float scale;

std::vector<BoneMod> boneMods;

// KEEP SKELETON AT THE END OF THE STRUCTURE
// it is to make a serialization hack for refEntity_t easier
// by memcpying up to skeleton and then serializing skeleton
Expand Down
3 changes: 2 additions & 1 deletion src/shared/client/cg_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ qhandle_t trap_R_RegisterAnimation( const char *name )
int trap_R_BuildSkeleton( refSkeleton_t *skel, qhandle_t anim, int startFrame, int endFrame, float frac, bool clearOrigin )
{
int result;
skel->numBones = 0;
VM::SendMsg<Render::BuildSkeletonMsg>(anim, startFrame, endFrame, frac, clearOrigin, *skel, result);
return result;
}
Expand All @@ -460,7 +461,7 @@ int trap_R_BlendSkeleton( refSkeleton_t *skel, const refSkeleton_t *blend, float

if ( skel->numBones != blend->numBones )
{
Log::Warn("trap_R_BlendSkeleton: different number of bones %d != %d", skel->numBones, blend->numBones);
// Log::Warn("trap_R_BlendSkeleton: different number of bones %d != %d", skel->numBones, blend->numBones);
return false;
}

Expand Down

0 comments on commit cf47328

Please sign in to comment.