Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Move most skeleton stuff to engine #1489

Draft
wants to merge 1 commit into
base: for-0.56.0/sync
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions src/engine/client/cg_msgdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,38 @@ 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;
Fixed Show fixed Hide fixed
}
};

// 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, tag));
stream.Write<std::string>( ent.tag );
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, tag));
ent.tag = stream.Read<std::string>();
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
162 changes: 158 additions & 4 deletions src/engine/renderer/tr_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2031,6 +2031,33 @@ static void R_SortDrawSurfs()
R_AddDrawViewCmd( false );
}

static void PositionEntityOnTag( refEntity_t* entity, const refEntity_t* parent, orientation_t* orientation ) {
// FIXME: allow origin offsets along tag?
VectorCopy( parent->origin, entity->origin );

for ( int i = 0; i < 3; i++ ) {
VectorMA( entity->origin, orientation->origin[i], parent->axis[i], entity->origin );
}

// had to cast away the const to avoid compiler problems...
AxisMultiply( orientation->axis, ( ( refEntity_t* ) parent )->axis, entity->axis );
entity->backlerp = parent->backlerp;
}

static void PositionRotatedEntityOnTag( refEntity_t* entity, const refEntity_t* parent, orientation_t* orientation ) {
// FIXME: allow origin offsets along tag?
VectorCopy( parent->origin, entity->origin );

for ( int i = 0; i < 3; i++ ) {
VectorMA( entity->origin, orientation->origin[i], parent->axis[i], entity->origin );
}

// had to cast away the const to avoid compiler problems...
axis_t tempAxis;
AxisMultiply( entity->axis, orientation->axis, tempAxis );
AxisMultiply( tempAxis, ( ( refEntity_t* ) parent )->axis, entity->axis );
}

/*
=============
R_AddEntitySurfaces
Expand Down Expand Up @@ -2095,19 +2122,146 @@ 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:
R_AddMD5Surfaces( ent );
/* 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 ); */
switch ( ent->e.positionOnTag ) {
case EntityTag::ON_TAG:
{
orientation_t orientation;
RE_LerpTagET( &orientation, &tr.refdef.entities[ent->e.attachmentEntity].e, ent->e.tag.c_str(), 0 );
PositionEntityOnTag( &ent->e, &tr.refdef.entities[ent->e.attachmentEntity].e, &orientation );
R_RotateEntityForViewParms( ent, &tr.viewParms, &tr.orientation );
break;
}

case EntityTag::ON_TAG_ROTATED:
{
orientation_t orientation;
RE_LerpTagET( &orientation, &tr.refdef.entities[ent->e.attachmentEntity].e, ent->e.tag.c_str(), 0 );
PositionRotatedEntityOnTag( &ent->e, &tr.refdef.entities[ent->e.attachmentEntity].e, &orientation );
R_RotateEntityForViewParms( ent, &tr.viewParms, &tr.orientation );
break;
}

case EntityTag::NONE:
default:
break;
}

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 );
}

if ( ent->e.boundsAdd ) {
matrix_t mat;
vec3_t bounds[2];

MatrixFromAngles( mat, ent->e.boundsRotation[0], ent->e.boundsRotation[1], ent->e.boundsRotation[2] );
MatrixTransformBounds( mat, ent->e.skeleton.bounds[0], ent->e.skeleton.bounds[1], bounds[0], bounds[1] );
BoundsAdd( ent->e.skeleton.bounds[0], ent->e.skeleton.bounds[1], bounds[0], bounds[1] );
}

if ( !( ent->e.renderfx & RF_NORENDER ) ) {
R_AddMD5Surfaces( ent );
}
break;

case modtype_t::MOD_IQM:
R_AddIQMSurfaces( ent );
{
/* 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 ); */
switch ( ent->e.positionOnTag ) {
case EntityTag::ON_TAG:
{
orientation_t orientation;
RE_LerpTagET( &orientation, &tr.refdef.entities[ent->e.attachmentEntity].e, ent->e.tag.c_str(), 0 );
PositionEntityOnTag( &ent->e, &tr.refdef.entities[ent->e.attachmentEntity].e, &orientation );
R_RotateEntityForViewParms( ent, &tr.viewParms, &tr.orientation );
break;
}

case EntityTag::ON_TAG_ROTATED:
{
orientation_t orientation;
RE_LerpTagET( &orientation, &tr.refdef.entities[ent->e.attachmentEntity].e, ent->e.tag.c_str(), 0 );
PositionRotatedEntityOnTag( &ent->e, &tr.refdef.entities[ent->e.attachmentEntity].e, &orientation );
R_RotateEntityForViewParms( ent, &tr.viewParms, &tr.orientation );
break;
}

case EntityTag::NONE:
default:
break;
}

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 );

if ( ent->e.boundsAdd ) {
matrix_t mat;
vec3_t bounds[2];

MatrixFromAngles( mat, ent->e.boundsRotation[0], ent->e.boundsRotation[1], ent->e.boundsRotation[2] );
MatrixTransformBounds( mat, ent->e.skeleton.bounds[0], ent->e.skeleton.bounds[1], bounds[0], bounds[1] );
BoundsAdd( ent->e.skeleton.bounds[0], ent->e.skeleton.bounds[1], bounds[0], bounds[1] );
}

if ( !( ent->e.renderfx & RF_NORENDER ) ) {
R_AddIQMSurfaces( ent );
}
break;
}

case modtype_t::MOD_BSP:
R_AddBSPModelSurfaces( ent );
Expand Down
35 changes: 35 additions & 0 deletions src/engine/renderer/tr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ using bool8_t = uint8_t;
// animation without needing to know the frame count
#define RF_FORCENOLOD 0x000400
#define RF_SWAPCULL 0x000800 // swap CT_FRONT_SIDED and CT_BACK_SIDED
#define RF_NORENDER 0x001000 // HACK: This is only used to put weapons in correct positions on skeletal models

// refdef flags
#define RDF_NOWORLDMODEL ( 1 << 0 ) // used for player configuration screen
Expand Down Expand Up @@ -156,6 +157,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 All @@ -170,6 +177,12 @@ struct alignas(16) refSkeleton_t

// XreaL END

enum class EntityTag {
NONE,
ON_TAG,
ON_TAG_ROTATED
};

struct refEntity_t
{
refEntityType_t reType;
Expand Down Expand Up @@ -211,6 +224,28 @@ 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;

int boundsAdd;
vec3_t boundsRotation;

EntityTag positionOnTag = EntityTag::NONE;
int attachmentEntity;
std::string tag;

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
13 changes: 10 additions & 3 deletions src/shared/client/cg_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,14 @@ void trap_R_ClearScene()
cmdBuffer.SendMsg<Render::ClearSceneMsg>();
}

void trap_R_AddRefEntityToScene( const refEntity_t *re )
/* HACK: We need the entityNum to get the correct positions for entities that need to be attached to another entity's bone
This must be equal to the r_numEntities in engine at the time of adding the entity */
static int entityNum;
int trap_R_AddRefEntityToScene( const refEntity_t *re )
{
cmdBuffer.SendMsg<Render::AddRefEntityToSceneMsg>(*re);
entityNum++;
return entityNum - 1;
}

void trap_R_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts )
Expand Down Expand Up @@ -362,6 +367,7 @@ void trap_R_AddAdditiveLightToScene( const vec3_t org, float intensity, float r,

void trap_R_RenderScene( const refdef_t *fd )
{
entityNum = 0;
cmdBuffer.SendMsg<Render::RenderSceneMsg>(*fd);
}

Expand Down Expand Up @@ -403,7 +409,7 @@ void trap_R_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs )
VectorCopy(mymaxs, maxs);
}

int trap_R_LerpTag( orientation_t *tag, const refEntity_t *refent, const char *tagName, int startIndex )
int trap_R_LerpTag( orientation_t *tag, const refEntity_t* refent, const char *tagName, int startIndex )
{
int result;
VM::SendMsg<Render::LerpTagMsg>(*refent, tagName, startIndex, *tag, result);
Expand Down Expand Up @@ -448,6 +454,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 +467,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
Loading
Loading