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 void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) = 0;
virtual float getAspectFactor(float vscale) { return 1.f; } virtual float getAspectFactor(float vscale) { return 1.f; }
virtual const TArray<TRS>* AttachAnimationData() { return nullptr; }; 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; } void SetVertexBuffer(int type, IModelVertexBuffer *buffer) { mVBuf[type] = buffer; }
IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; } IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; }

View file

@ -113,7 +113,7 @@ public:
void BuildVertexBuffer(FModelRenderer* renderer) override; void BuildVertexBuffer(FModelRenderer* renderer) override;
void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override; void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override;
const TArray<TRS>* AttachAnimationData() 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: private:
void LoadGeometry(); void LoadGeometry();

View file

@ -510,20 +510,16 @@ const TArray<TRS>* IQMModel::AttachAnimationData()
return &TRSData; 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; const TArray<TRS>& animationFrames = &animationData ? animationData : TRSData;
int numbones = Joints.Size(); int numbones = Joints.Size();
if (actor->boneComponentData == nullptr) if(actor->boneComponentData->trscomponents[index].Size() != numbones)
{ actor->boneComponentData->trscomponents[index].Resize(numbones);
auto ptr = Create<DBoneComponents>(); if (actor->boneComponentData->trsmatrix[index].Size() != numbones)
ptr->trscomponents.Resize(numbones); actor->boneComponentData->trsmatrix[index].Resize(numbones);
ptr->trsmatrix.Resize(numbones);
actor->boneComponentData = ptr;
GC::WriteBarrier(actor, ptr);
}
frame1 = clamp(frame1, 0, ((int)animationFrames.Size() - 1) / numbones); frame1 = clamp(frame1, 0, ((int)animationFrames.Size() - 1) / numbones);
frame2 = clamp(frame2, 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 from = animationFrames[offset1 + i];
TRS to = animationFrames[offset2 + 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.translation = from.translation * invt + to.translation * t;
bone.rotation = from.rotation * invt; bone.rotation = from.rotation * invt;
if ((bone.rotation | to.rotation * t) < 0) 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]) if (Joints[i].Parent >= 0 && modifiedBone[Joints[i].Parent])
{ {
actor->boneComponentData->trscomponents[i] = bone; actor->boneComponentData->trscomponents[index][i] = bone;
modifiedBone[i] = true; 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; modifiedBone[i] = false;
continue; continue;
} }
else else
{ {
actor->boneComponentData->trscomponents[i] = bone; actor->boneComponentData->trscomponents[index][i] = bone;
modifiedBone[i] = true; 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++) for (uint32_t j = 0; j < numbones; j++)
{ {

View file

@ -695,22 +695,12 @@ class DBoneComponents : public DObject
{ {
DECLARE_CLASS(DBoneComponents, DObject); DECLARE_CLASS(DBoneComponents, DObject);
public: public:
TArray<TRS> trscomponents; TArray<TArray<TRS>> trscomponents;
TArray<VSMatrix> trsmatrix; TArray<TArray<VSMatrix>> trsmatrix;
DBoneComponents() = default; DBoneComponents() = default;
}; };
class DBoneManipulations : public DObject
{
DECLARE_CLASS(DBoneComponents, DObject);
public:
TArray<TRS> boneComponentsNew;
TArray<TRS> boneComponentsOld;
DBoneManipulations() = default;
};
class DViewPosition : public DObject class DViewPosition : public DObject
{ {
DECLARE_CLASS(DViewPosition, DObject); DECLARE_CLASS(DViewPosition, DObject);
@ -1108,7 +1098,6 @@ public:
double FloatSpeed; double FloatSpeed;
TObjPtr<DActorModelData*> modelData; TObjPtr<DActorModelData*> modelData;
TObjPtr<DBoneComponents*> boneComponentData; TObjPtr<DBoneComponents*> boneComponentData;
TObjPtr<DBoneManipulations*> boneManipulationData;
// interaction info // interaction info
FBlockNode *BlockNode; // links in blocks (if needed) 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); if (self->RenderStyle == LegacyRenderStyles[i]) ACTION_RETURN_INT(i);
} }
ACTION_RETURN_INT(-1); // no symbolic constant exists to handle this style. 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(DActorModelData, false, false);
IMPLEMENT_CLASS(DBoneComponents, false, false); IMPLEMENT_CLASS(DBoneComponents, false, false);
IMPLEMENT_CLASS(DBoneManipulations, false, false);
IMPLEMENT_CLASS(AActor, false, true) IMPLEMENT_CLASS(AActor, false, true)
IMPLEMENT_POINTERS_START(AActor) IMPLEMENT_POINTERS_START(AActor)
@ -177,7 +176,6 @@ IMPLEMENT_POINTERS_START(AActor)
IMPLEMENT_POINTER(ViewPos) IMPLEMENT_POINTER(ViewPos)
IMPLEMENT_POINTER(modelData) IMPLEMENT_POINTER(modelData)
IMPLEMENT_POINTER(boneComponentData) IMPLEMENT_POINTER(boneComponentData)
IMPLEMENT_POINTER(boneManipulationData)
IMPLEMENT_POINTERS_END IMPLEMENT_POINTERS_END
AActor::~AActor () AActor::~AActor ()

View file

@ -356,6 +356,15 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
bool nextFrame = smfNext && modelframe != modelframenext; 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) if (animationid >= 0)
{ {
FModel* animation = Models[animationid]; FModel* animation = Models[animationid];
@ -363,7 +372,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
if (!(smf->flags & MDL_MODELSAREATTACHMENTS) || evaluatedSingle == false) 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); boneStartingPosition = renderer->SetupFrame(animation, 0, 0, 0, boneData, -1);
evaluatedSingle = true; evaluatedSingle = true;
} }
@ -372,7 +381,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
{ {
if (!(smf->flags & MDL_MODELSAREATTACHMENTS) || evaluatedSingle == false) 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); boneStartingPosition = renderer->SetupFrame(mdl, 0, 0, 0, boneData, -1);
evaluatedSingle = true; 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); 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); 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_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) void A_SetFriendly (bool set)
{ {

View file

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