Skip to content

Commit 06b3c18

Browse files
committed
Move skeleton building and blending to engine
1 parent 782d78f commit 06b3c18

File tree

7 files changed

+257
-13
lines changed

7 files changed

+257
-13
lines changed

src/engine/client/cg_msgdef.h

+24-4
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,38 @@ namespace Util {
9696
}
9797
};
9898

99+
template<> struct SerializeTraits<std::vector<BoneMod>> {
100+
static void Write( Writer& stream, const std::vector<BoneMod>& boneMods ) {
101+
stream.WriteSize( boneMods.size() );
102+
stream.WriteData( boneMods.data(), boneMods.size() * sizeof( BoneMod ) );
103+
}
104+
105+
static std::vector<BoneMod> Read( Reader& stream ) {
106+
std::vector<BoneMod> boneMods;
107+
const size_t size = stream.ReadSize<BoneMod>();
108+
boneMods.resize( size );
109+
stream.ReadData( boneMods.data(), size * sizeof( BoneMod ) );
110+
return boneMods;
111+
}
112+
};
113+
99114
// Use that bone optimization for refEntity_t
100115
template<> struct SerializeTraits<refEntity_t> {
101116
static void Write(Writer& stream, const refEntity_t& ent)
102117
{
103-
stream.WriteData(&ent, offsetof(refEntity_t, skeleton));
104-
stream.Write<refSkeleton_t>(ent.skeleton);
118+
stream.WriteData(&ent, offsetof(refEntity_t, tag));
119+
stream.Write<std::string>( ent.tag );
120+
stream.Write<std::vector<BoneMod>>( ent.boneMods );
121+
// stream.Write<refSkeleton_t>(ent.skeleton);
105122
}
123+
106124
static refEntity_t Read(Reader& stream)
107125
{
108126
refEntity_t ent;
109-
stream.ReadData(&ent, offsetof(refEntity_t, skeleton));
110-
ent.skeleton = stream.Read<refSkeleton_t>();
127+
stream.ReadData(&ent, offsetof(refEntity_t, tag));
128+
ent.tag = stream.Read<std::string>();
129+
ent.boneMods = stream.Read<std::vector<BoneMod>>();
130+
// ent.skeleton = stream.Read<refSkeleton_t>();
111131
return ent;
112132
}
113133
};

src/engine/renderer/tr_animation.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,32 @@ static int IQMBuildSkeleton( refSkeleton_t *skel, skelAnimation_t *skelAnim,
13131313
return true;
13141314
}
13151315

1316+
void R_TransformSkeleton( refSkeleton_t* skel, const float scale ) {
1317+
skel->scale = scale;
1318+
1319+
switch ( skel->type ) {
1320+
case refSkeletonType_t::SK_INVALID:
1321+
case refSkeletonType_t::SK_ABSOLUTE:
1322+
return;
1323+
1324+
default:
1325+
break;
1326+
}
1327+
1328+
// calculate absolute transforms
1329+
for ( refBone_t* bone = &skel->bones[0]; bone < &skel->bones[skel->numBones]; bone++ ) {
1330+
if ( bone->parentIndex >= 0 ) {
1331+
refBone_t* parent;
1332+
1333+
parent = &skel->bones[bone->parentIndex];
1334+
1335+
TransCombine( &bone->t, &parent->t, &bone->t );
1336+
}
1337+
}
1338+
1339+
skel->type = refSkeletonType_t::SK_ABSOLUTE;
1340+
}
1341+
13161342
/*
13171343
==============
13181344
RE_BuildSkeleton
@@ -1468,6 +1494,7 @@ int RE_BuildSkeleton( refSkeleton_t *skel, qhandle_t hAnim, int startFrame, int
14681494
}
14691495

14701496
// FIXME: clear existing bones and bounds?
1497+
skel->numBones = 0;
14711498
return false;
14721499
}
14731500

src/engine/renderer/tr_local.h

+1
Original file line numberDiff line numberDiff line change
@@ -3730,6 +3730,7 @@ inline bool checkGLErrors()
37303730
int RE_CheckSkeleton( refSkeleton_t *skel, qhandle_t hModel, qhandle_t hAnim );
37313731
int RE_BuildSkeleton( refSkeleton_t *skel, qhandle_t anim, int startFrame, int endFrame, float frac,
37323732
bool clearOrigin );
3733+
void R_TransformSkeleton( refSkeleton_t* skel, const float scale );
37333734
int RE_BlendSkeleton( refSkeleton_t *skel, const refSkeleton_t *blend, float frac );
37343735
int RE_AnimNumFrames( qhandle_t hAnim );
37353736
int RE_AnimFrameRate( qhandle_t hAnim );

src/engine/renderer/tr_main.cpp

+158-4
Original file line numberDiff line numberDiff line change
@@ -2031,6 +2031,33 @@ static void R_SortDrawSurfs()
20312031
R_AddDrawViewCmd( false );
20322032
}
20332033

2034+
static void PositionEntityOnTag( refEntity_t* entity, const refEntity_t* parent, orientation_t* orientation ) {
2035+
// FIXME: allow origin offsets along tag?
2036+
VectorCopy( parent->origin, entity->origin );
2037+
2038+
for ( int i = 0; i < 3; i++ ) {
2039+
VectorMA( entity->origin, orientation->origin[i], parent->axis[i], entity->origin );
2040+
}
2041+
2042+
// had to cast away the const to avoid compiler problems...
2043+
AxisMultiply( orientation->axis, ( ( refEntity_t* ) parent )->axis, entity->axis );
2044+
entity->backlerp = parent->backlerp;
2045+
}
2046+
2047+
static void PositionRotatedEntityOnTag( refEntity_t* entity, const refEntity_t* parent, orientation_t* orientation ) {
2048+
// FIXME: allow origin offsets along tag?
2049+
VectorCopy( parent->origin, entity->origin );
2050+
2051+
for ( int i = 0; i < 3; i++ ) {
2052+
VectorMA( entity->origin, orientation->origin[i], parent->axis[i], entity->origin );
2053+
}
2054+
2055+
// had to cast away the const to avoid compiler problems...
2056+
axis_t tempAxis;
2057+
AxisMultiply( entity->axis, orientation->axis, tempAxis );
2058+
AxisMultiply( tempAxis, ( ( refEntity_t* ) parent )->axis, entity->axis );
2059+
}
2060+
20342061
/*
20352062
=============
20362063
R_AddEntitySurfaces
@@ -2095,19 +2122,146 @@ void R_AddEntitySurfaces()
20952122
}
20962123
else
20972124
{
2098-
switch ( tr.currentModel->type )
2099-
{
2125+
switch ( tr.currentModel->type ) {
21002126
case modtype_t::MOD_MESH:
21012127
R_AddMDVSurfaces( ent );
21022128
break;
21032129

21042130
case modtype_t::MOD_MD5:
2105-
R_AddMD5Surfaces( ent );
2131+
/* Log::Warn("%i %s: old: %i-%i %f new: %i-%i %f | %f %f", ent->e.animationHandle,
2132+
R_GetAnimationByHandle( ent->e.animationHandle )->name, ent->e.startFrame,
2133+
ent->e.endFrame, ent->e.lerp, ent->e.startFrame2, ent->e.endFrame2, ent->e.lerp2,
2134+
ent->e.blendLerp, ent->e.scale ); */
2135+
switch ( ent->e.positionOnTag ) {
2136+
case EntityTag::ON_TAG:
2137+
{
2138+
orientation_t orientation;
2139+
RE_LerpTagET( &orientation, &tr.refdef.entities[ent->e.attachmentEntity].e, ent->e.tag.c_str(), 0 );
2140+
PositionEntityOnTag( &ent->e, &tr.refdef.entities[ent->e.attachmentEntity].e, &orientation );
2141+
R_RotateEntityForViewParms( ent, &tr.viewParms, &tr.orientation );
2142+
break;
2143+
}
2144+
2145+
case EntityTag::ON_TAG_ROTATED:
2146+
{
2147+
orientation_t orientation;
2148+
RE_LerpTagET( &orientation, &tr.refdef.entities[ent->e.attachmentEntity].e, ent->e.tag.c_str(), 0 );
2149+
PositionRotatedEntityOnTag( &ent->e, &tr.refdef.entities[ent->e.attachmentEntity].e, &orientation );
2150+
R_RotateEntityForViewParms( ent, &tr.viewParms, &tr.orientation );
2151+
break;
2152+
}
2153+
2154+
case EntityTag::NONE:
2155+
default:
2156+
break;
2157+
}
2158+
2159+
if ( ent->e.scale == 0 ) {
2160+
ent->e.scale = 1;
2161+
}
2162+
if ( ent->e.animationHandle == 0 ) {
2163+
ent->e.animationHandle = ent->e.animationHandle2;
2164+
} else if ( ent->e.animationHandle2 == 0 ) {
2165+
ent->e.animationHandle2 = ent->e.animationHandle;
2166+
}
2167+
2168+
RE_BuildSkeleton( &ent->e.skeleton, ent->e.animationHandle, ent->e.startFrame, ent->e.endFrame,
2169+
ent->e.lerp, ent->e.clearOrigin );
2170+
ent->e.skeleton.scale = ent->e.scale;
2171+
if ( ent->e.blendLerp > 0.0 ) {
2172+
refSkeleton_t skel;
2173+
RE_BuildSkeleton( &skel, ent->e.animationHandle2, ent->e.startFrame2, ent->e.endFrame2,
2174+
ent->e.lerp2, ent->e.clearOrigin2 );
2175+
RE_BlendSkeleton( &ent->e.skeleton, &skel, ent->e.blendLerp );
2176+
}
2177+
2178+
for ( const BoneMod& boneMod : ent->e.boneMods ) {
2179+
QuatMultiply2( ent->e.skeleton.bones[boneMod.index].t.rot, boneMod.rotation );
2180+
}
2181+
2182+
if ( ent->e.boundsAdd ) {
2183+
matrix_t mat;
2184+
vec3_t bounds[2];
2185+
2186+
MatrixFromAngles( mat, ent->e.boundsRotation[0], ent->e.boundsRotation[1], ent->e.boundsRotation[2] );
2187+
MatrixTransformBounds( mat, ent->e.skeleton.bounds[0], ent->e.skeleton.bounds[1], bounds[0], bounds[1] );
2188+
BoundsAdd( ent->e.skeleton.bounds[0], ent->e.skeleton.bounds[1], bounds[0], bounds[1] );
2189+
}
2190+
2191+
if ( !( ent->e.renderfx & RF_NORENDER ) ) {
2192+
R_AddMD5Surfaces( ent );
2193+
}
21062194
break;
21072195

21082196
case modtype_t::MOD_IQM:
2109-
R_AddIQMSurfaces( ent );
2197+
{
2198+
/* Log::Warn("%i %s: old: %i-%i %f new: %i-%i %f | %f %f", ent->e.animationHandle,
2199+
R_GetAnimationByHandle( ent->e.animationHandle )->name, ent->e.startFrame,
2200+
ent->e.endFrame, ent->e.lerp, ent->e.startFrame2, ent->e.endFrame2, ent->e.lerp2,
2201+
ent->e.blendLerp, ent->e.scale ); */
2202+
switch ( ent->e.positionOnTag ) {
2203+
case EntityTag::ON_TAG:
2204+
{
2205+
orientation_t orientation;
2206+
RE_LerpTagET( &orientation, &tr.refdef.entities[ent->e.attachmentEntity].e, ent->e.tag.c_str(), 0 );
2207+
PositionEntityOnTag( &ent->e, &tr.refdef.entities[ent->e.attachmentEntity].e, &orientation );
2208+
R_RotateEntityForViewParms( ent, &tr.viewParms, &tr.orientation );
2209+
break;
2210+
}
2211+
2212+
case EntityTag::ON_TAG_ROTATED:
2213+
{
2214+
orientation_t orientation;
2215+
RE_LerpTagET( &orientation, &tr.refdef.entities[ent->e.attachmentEntity].e, ent->e.tag.c_str(), 0 );
2216+
PositionRotatedEntityOnTag( &ent->e, &tr.refdef.entities[ent->e.attachmentEntity].e, &orientation );
2217+
R_RotateEntityForViewParms( ent, &tr.viewParms, &tr.orientation );
2218+
break;
2219+
}
2220+
2221+
case EntityTag::NONE:
2222+
default:
2223+
break;
2224+
}
2225+
2226+
bool transform = true;
2227+
if ( ent->e.scale == 0 ) {
2228+
ent->e.scale = 1;
2229+
}
2230+
if ( ent->e.animationHandle == 0 ) {
2231+
ent->e.animationHandle = ent->e.animationHandle2;
2232+
} else if ( ent->e.animationHandle2 == 0 ) {
2233+
ent->e.animationHandle2 = ent->e.animationHandle;
2234+
}
2235+
2236+
ent->e.skeleton.scale = ent->e.scale;
2237+
RE_BuildSkeleton( &ent->e.skeleton, ent->e.animationHandle, ent->e.startFrame, ent->e.endFrame,
2238+
ent->e.lerp, ent->e.clearOrigin );
2239+
if ( ent->e.blendLerp > 0.0 ) {
2240+
refSkeleton_t skel;
2241+
RE_BuildSkeleton( &skel, ent->e.animationHandle2, ent->e.startFrame2, ent->e.endFrame2,
2242+
ent->e.lerp2, ent->e.clearOrigin2 );
2243+
RE_BlendSkeleton( &ent->e.skeleton, &skel, ent->e.blendLerp );
2244+
}
2245+
2246+
for ( const BoneMod& boneMod : ent->e.boneMods ) {
2247+
QuatMultiply2( ent->e.skeleton.bones[boneMod.index].t.rot, boneMod.rotation );
2248+
}
2249+
R_TransformSkeleton( &ent->e.skeleton, ent->e.scale );
2250+
2251+
if ( ent->e.boundsAdd ) {
2252+
matrix_t mat;
2253+
vec3_t bounds[2];
2254+
2255+
MatrixFromAngles( mat, ent->e.boundsRotation[0], ent->e.boundsRotation[1], ent->e.boundsRotation[2] );
2256+
MatrixTransformBounds( mat, ent->e.skeleton.bounds[0], ent->e.skeleton.bounds[1], bounds[0], bounds[1] );
2257+
BoundsAdd( ent->e.skeleton.bounds[0], ent->e.skeleton.bounds[1], bounds[0], bounds[1] );
2258+
}
2259+
2260+
if ( !( ent->e.renderfx & RF_NORENDER ) ) {
2261+
R_AddIQMSurfaces( ent );
2262+
}
21102263
break;
2264+
}
21112265

21122266
case modtype_t::MOD_BSP:
21132267
R_AddBSPModelSurfaces( ent );

src/engine/renderer/tr_types.h

+35
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ using bool8_t = uint8_t;
7070
// animation without needing to know the frame count
7171
#define RF_FORCENOLOD 0x000400
7272
#define RF_SWAPCULL 0x000800 // swap CT_FRONT_SIDED and CT_BACK_SIDED
73+
#define RF_NORENDER 0x001000 // HACK: This is only used to put weapons in correct positions on skeletal models
7374

7475
// refdef flags
7576
#define RDF_NOWORLDMODEL ( 1 << 0 ) // used for player configuration screen
@@ -156,6 +157,12 @@ enum class refSkeletonType_t
156157
SK_ABSOLUTE
157158
};
158159

160+
struct BoneMod {
161+
int index;
162+
vec3_t translation;
163+
quat_t rotation;
164+
};
165+
159166
struct alignas(16) refSkeleton_t
160167
{
161168
refSkeletonType_t type; // skeleton has been reset
@@ -170,6 +177,12 @@ struct alignas(16) refSkeleton_t
170177

171178
// XreaL END
172179

180+
enum class EntityTag {
181+
NONE,
182+
ON_TAG,
183+
ON_TAG_ROTATED
184+
};
185+
173186
struct refEntity_t
174187
{
175188
refEntityType_t reType;
@@ -211,6 +224,28 @@ struct refEntity_t
211224

212225
int altShaderIndex;
213226

227+
qhandle_t animationHandle;
228+
int startFrame;
229+
int endFrame;
230+
float lerp;
231+
int clearOrigin;
232+
qhandle_t animationHandle2;
233+
int startFrame2;
234+
int endFrame2;
235+
float lerp2;
236+
int clearOrigin2;
237+
float blendLerp;
238+
float scale;
239+
240+
int boundsAdd;
241+
vec3_t boundsRotation;
242+
243+
EntityTag positionOnTag = EntityTag::NONE;
244+
int attachmentEntity;
245+
std::string tag;
246+
247+
std::vector<BoneMod> boneMods;
248+
214249
// KEEP SKELETON AT THE END OF THE STRUCTURE
215250
// it is to make a serialization hack for refEntity_t easier
216251
// by memcpying up to skeleton and then serializing skeleton

src/shared/client/cg_api.cpp

+10-3
Original file line numberDiff line numberDiff line change
@@ -288,9 +288,14 @@ void trap_R_ClearScene()
288288
cmdBuffer.SendMsg<Render::ClearSceneMsg>();
289289
}
290290

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

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

363368
void trap_R_RenderScene( const refdef_t *fd )
364369
{
370+
entityNum = 0;
365371
cmdBuffer.SendMsg<Render::RenderSceneMsg>(*fd);
366372
}
367373

@@ -403,7 +409,7 @@ void trap_R_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs )
403409
VectorCopy(mymaxs, maxs);
404410
}
405411

406-
int trap_R_LerpTag( orientation_t *tag, const refEntity_t *refent, const char *tagName, int startIndex )
412+
int trap_R_LerpTag( orientation_t *tag, const refEntity_t* refent, const char *tagName, int startIndex )
407413
{
408414
int result;
409415
VM::SendMsg<Render::LerpTagMsg>(*refent, tagName, startIndex, *tag, result);
@@ -448,6 +454,7 @@ qhandle_t trap_R_RegisterAnimation( const char *name )
448454
int trap_R_BuildSkeleton( refSkeleton_t *skel, qhandle_t anim, int startFrame, int endFrame, float frac, bool clearOrigin )
449455
{
450456
int result;
457+
skel->numBones = 0;
451458
VM::SendMsg<Render::BuildSkeletonMsg>(anim, startFrame, endFrame, frac, clearOrigin, *skel, result);
452459
return result;
453460
}
@@ -460,7 +467,7 @@ int trap_R_BlendSkeleton( refSkeleton_t *skel, const refSkeleton_t *blend, float
460467

461468
if ( skel->numBones != blend->numBones )
462469
{
463-
Log::Warn("trap_R_BlendSkeleton: different number of bones %d != %d", skel->numBones, blend->numBones);
470+
// Log::Warn("trap_R_BlendSkeleton: different number of bones %d != %d", skel->numBones, blend->numBones);
464471
return false;
465472
}
466473

0 commit comments

Comments
 (0)