IQM Refactor Milestone

- Removed bone manipulation code
- Implemented an index in calculateBones to optimize multi-armature actors
- Moved the bone storage object's creation to RenderModels so that the armature array can be sized there
This commit is contained in:
Shiny Metagross 2022-10-28 15:09:42 -07:00 committed by Christoph Oelckers
parent 7092971331
commit f7c3615d3b
9 changed files with 26 additions and 145 deletions

View File

@ -77,7 +77,7 @@ public:
virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) = 0;
virtual float getAspectFactor(float vscale) { return 1.f; }
virtual const TArray<TRS>* AttachAnimationData() { return nullptr; };
virtual const TArray<VSMatrix> CalculateBones(int frame1, int frame2, double inter, const TArray<TRS>& animationData, AActor* actor) { return {}; };
virtual const TArray<VSMatrix> CalculateBones(int frame1, int frame2, double inter, const TArray<TRS>& animationData, AActor* actor, int index) { return {}; };
void SetVertexBuffer(int type, IModelVertexBuffer *buffer) { mVBuf[type] = buffer; }
IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; }

View File

@ -113,7 +113,7 @@ public:
void BuildVertexBuffer(FModelRenderer* renderer) override;
void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override;
const TArray<TRS>* AttachAnimationData() override;
const TArray<VSMatrix> CalculateBones(int frame1, int frame2, double inter, const TArray<TRS>& animationData, AActor* actor) override;
const TArray<VSMatrix> CalculateBones(int frame1, int frame2, double inter, const TArray<TRS>& animationData, AActor* actor, int index) override;
private:
void LoadGeometry();

View File

@ -510,20 +510,16 @@ const TArray<TRS>* IQMModel::AttachAnimationData()
return &TRSData;
}
const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, double inter, const TArray<TRS>& animationData, AActor* actor)
const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, double inter, const TArray<TRS>& animationData, AActor* actor, int index)
{
const TArray<TRS>& animationFrames = &animationData ? animationData : TRSData;
int numbones = Joints.Size();
if (actor->boneComponentData == nullptr)
{
auto ptr = Create<DBoneComponents>();
ptr->trscomponents.Resize(numbones);
ptr->trsmatrix.Resize(numbones);
actor->boneComponentData = ptr;
GC::WriteBarrier(actor, ptr);
}
if(actor->boneComponentData->trscomponents[index].Size() != numbones)
actor->boneComponentData->trscomponents[index].Resize(numbones);
if (actor->boneComponentData->trsmatrix[index].Size() != numbones)
actor->boneComponentData->trsmatrix[index].Resize(numbones);
frame1 = clamp(frame1, 0, ((int)animationFrames.Size() - 1) / numbones);
frame2 = clamp(frame2, 0, ((int)animationFrames.Size() - 1) / numbones);
@ -547,23 +543,6 @@ const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, double i
TRS from = animationFrames[offset1 + i];
TRS to = animationFrames[offset2 + i];
if (actor->boneManipulationData != nullptr)
{
if (i < actor->boneManipulationData->boneComponentsOld.Size())
{
from.translation += actor->boneManipulationData->boneComponentsOld[i].translation;
from.rotation *= actor->boneManipulationData->boneComponentsOld[i].rotation;
from.scaling += actor->boneManipulationData->boneComponentsOld[i].scaling;
}
if (i < actor->boneManipulationData->boneComponentsNew.Size())
{
to.translation += actor->boneManipulationData->boneComponentsNew[i].translation;
to.rotation *= actor->boneManipulationData->boneComponentsNew[i].rotation;
to.scaling += actor->boneManipulationData->boneComponentsNew[i].scaling;
}
}
bone.translation = from.translation * invt + to.translation * t;
bone.rotation = from.rotation * invt;
if ((bone.rotation | to.rotation * t) < 0)
@ -576,18 +555,18 @@ const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, double i
if (Joints[i].Parent >= 0 && modifiedBone[Joints[i].Parent])
{
actor->boneComponentData->trscomponents[i] = bone;
actor->boneComponentData->trscomponents[index][i] = bone;
modifiedBone[i] = true;
}
else if (actor->boneComponentData->trscomponents[i].Equals(bone))
else if (actor->boneComponentData->trscomponents[index][i].Equals(bone))
{
bones[i] = actor->boneComponentData->trsmatrix[i];
bones[i] = actor->boneComponentData->trsmatrix[index][i];
modifiedBone[i] = false;
continue;
}
else
{
actor->boneComponentData->trscomponents[i] = bone;
actor->boneComponentData->trscomponents[index][i] = bone;
modifiedBone[i] = true;
}
@ -612,7 +591,7 @@ const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, double i
}
}
actor->boneComponentData->trsmatrix = bones;
actor->boneComponentData->trsmatrix[index] = bones;
for (uint32_t j = 0; j < numbones; j++)
{

View File

@ -695,22 +695,12 @@ class DBoneComponents : public DObject
{
DECLARE_CLASS(DBoneComponents, DObject);
public:
TArray<TRS> trscomponents;
TArray<VSMatrix> trsmatrix;
TArray<TArray<TRS>> trscomponents;
TArray<TArray<VSMatrix>> trsmatrix;
DBoneComponents() = default;
};
class DBoneManipulations : public DObject
{
DECLARE_CLASS(DBoneComponents, DObject);
public:
TArray<TRS> boneComponentsNew;
TArray<TRS> boneComponentsOld;
DBoneManipulations() = default;
};
class DViewPosition : public DObject
{
DECLARE_CLASS(DViewPosition, DObject);
@ -1108,7 +1098,6 @@ public:
double FloatSpeed;
TObjPtr<DActorModelData*> modelData;
TObjPtr<DBoneComponents*> boneComponentData;
TObjPtr<DBoneManipulations*> boneManipulationData;
// interaction info
FBlockNode *BlockNode; // links in blocks (if needed)

View File

@ -5194,91 +5194,4 @@ DEFINE_ACTION_FUNCTION(AActor, GetRenderStyle)
if (self->RenderStyle == LegacyRenderStyles[i]) ACTION_RETURN_INT(i);
}
ACTION_RETURN_INT(-1); // no symbolic constant exists to handle this style.
}
//==========================================================================
//
// A_ManipulateBone(a bunch of crap)
//
// This function allows manipulating a bone
//==========================================================================
enum ManipulateBoneFlags
{
BM_USEEULER = 1
};
DEFINE_ACTION_FUNCTION(AActor, A_ManipulateBone)
{
PARAM_ACTION_PROLOGUE(AActor);
PARAM_INT(modelindex);
PARAM_INT(boneindex);
PARAM_FLOAT(positionX);
PARAM_FLOAT(positionY);
PARAM_FLOAT(positionZ);
PARAM_FLOAT(rotationX);
PARAM_FLOAT(rotationY);
PARAM_FLOAT(rotationZ);
PARAM_FLOAT(rotationW);
PARAM_FLOAT(scaleX);
PARAM_FLOAT(scaleY);
PARAM_FLOAT(scaleZ);
PARAM_INT(flags);
if (self == nullptr)
ACTION_RETURN_BOOL(false);
AActor* mobj = ACTION_CALL_FROM_INVENTORY() ? self : stateowner;
if (mobj->boneManipulationData == nullptr)
{
auto ptr = Create<DBoneManipulations>();
ptr->boneComponentsNew = *new TArray<TRS>();
ptr->boneComponentsOld = *new TArray<TRS>();
mobj->boneManipulationData = ptr;
GC::WriteBarrier(mobj, ptr);
}
while(boneindex >= mobj->boneManipulationData->boneComponentsNew.Size())
mobj->boneManipulationData->boneComponentsNew.Push(TRS());
while (boneindex >= mobj->boneManipulationData->boneComponentsOld.Size())
mobj->boneManipulationData->boneComponentsOld.Push(TRS());
if (flags & BM_USEEULER)
{
rotationX = rotationX * 3.14159265359f / 180.0f;
rotationY = rotationY * 3.14159265359f / 180.0f;
rotationZ = rotationZ * 3.14159265359f / 180.0f;
double cr = cos(rotationX * 0.5);
double sr = sin(rotationX * 0.5);
double cp = cos(rotationZ * 0.5);
double sp = sin(rotationZ * 0.5);
double cy = cos(rotationY * 0.5);
double sy = sin(rotationY * 0.5);
rotationW = cr * cp * cy + sr * sp * sy;
rotationX = sr * cp * cy - cr * sp * sy;
rotationY = cr * sp * cy + sr * cp * sy;
rotationZ = cr * cp * sy - sr * sp * cy;
//Printf("Rotation X is: %f\n", rotationX);
//Printf("Rotation Y is: %f\n", rotationY);
//Printf("Rotation Z is: %f\n", rotationZ);
//Printf("Rotation W is: %f\n", rotationW);
}
mobj->boneManipulationData->boneComponentsOld[boneindex] = mobj->boneManipulationData->boneComponentsNew[boneindex];
mobj->boneManipulationData->boneComponentsNew[boneindex].translation.X = positionX;
mobj->boneManipulationData->boneComponentsNew[boneindex].translation.Y = positionZ;
mobj->boneManipulationData->boneComponentsNew[boneindex].translation.Z = positionY;
mobj->boneManipulationData->boneComponentsNew[boneindex].rotation.X = rotationX;
mobj->boneManipulationData->boneComponentsNew[boneindex].rotation.Y = rotationY;
mobj->boneManipulationData->boneComponentsNew[boneindex].rotation.Z = rotationZ;
mobj->boneManipulationData->boneComponentsNew[boneindex].rotation.W = rotationW;
mobj->boneManipulationData->boneComponentsNew[boneindex].scaling.X = scaleX;
mobj->boneManipulationData->boneComponentsNew[boneindex].scaling.Y = scaleZ;
mobj->boneManipulationData->boneComponentsNew[boneindex].scaling.Z = scaleY;
return 0;
}
}

View File

@ -160,7 +160,6 @@ CVAR (Int, cl_bloodtype, 0, CVAR_ARCHIVE);
IMPLEMENT_CLASS(DActorModelData, false, false);
IMPLEMENT_CLASS(DBoneComponents, false, false);
IMPLEMENT_CLASS(DBoneManipulations, false, false);
IMPLEMENT_CLASS(AActor, false, true)
IMPLEMENT_POINTERS_START(AActor)
@ -177,7 +176,6 @@ IMPLEMENT_POINTERS_START(AActor)
IMPLEMENT_POINTER(ViewPos)
IMPLEMENT_POINTER(modelData)
IMPLEMENT_POINTER(boneComponentData)
IMPLEMENT_POINTER(boneManipulationData)
IMPLEMENT_POINTERS_END
AActor::~AActor ()

View File

@ -356,6 +356,15 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
bool nextFrame = smfNext && modelframe != modelframenext;
if (actor->boneComponentData == nullptr)
{
auto ptr = Create<DBoneComponents>();
ptr->trscomponents.Resize(modelsamount);
ptr->trsmatrix.Resize(modelsamount);
actor->boneComponentData = ptr;
GC::WriteBarrier(actor, ptr);
}
if (animationid >= 0)
{
FModel* animation = Models[animationid];
@ -363,7 +372,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
if (!(smf->flags & MDL_MODELSAREATTACHMENTS) || evaluatedSingle == false)
{
boneData = animation->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, *animationData, actor);
boneData = animation->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, *animationData, actor, i);
boneStartingPosition = renderer->SetupFrame(animation, 0, 0, 0, boneData, -1);
evaluatedSingle = true;
}
@ -372,7 +381,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
{
if (!(smf->flags & MDL_MODELSAREATTACHMENTS) || evaluatedSingle == false)
{
boneData = mdl->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, *animationData, actor);
boneData = mdl->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, *animationData, actor, i);
boneStartingPosition = renderer->SetupFrame(mdl, 0, 0, 0, boneData, -1);
evaluatedSingle = true;
}

View File

@ -1134,7 +1134,6 @@ class Actor : Thinker native
deprecated("2.3", "Use 'b<FlagName> = [true/false]' instead") native void A_ChangeFlag(string flagname, bool value);
native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE);
action native void A_ChangeModel(name modeldef, int modelindex = 0, string modelpath = "", name model = "", int skinindex = 0, string skinpath = "", name skin = "", int flags = 0, int generatorindex = -1, int animationindex = 0, string animationpath = "", name animation = "");
action native void A_ManipulateBone(int modelindex, int boneindex, float positionX = 0, float positionY = 0, float positionZ = 0, float rotationX = 0, float rotationY = 0, float rotationZ = 0, float rotationW = 0, float scaleX = 0, float scaleY = 0, float scaleZ = 0, int flags = 0);
void A_SetFriendly (bool set)
{

View File

@ -373,12 +373,6 @@ enum ChangeModelFlags
CMDL_USESURFACESKIN = 1 << 2,
};
// Manipulate Bone Flags
enum ManipulateBoneFlags
{
BM_USEEULER = 1
};
// Activation flags
enum EActivationFlags
{