Bone manipulation start

- Bone manipulation is largely finished, but I need to figure out how to multiply quaternions
This commit is contained in:
Shiny Metagross 2022-10-27 16:05:03 -07:00 committed by Christoph Oelckers
parent 317e163fcf
commit 28444d4cfd
6 changed files with 128 additions and 5 deletions

View File

@ -543,15 +543,35 @@ const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, double i
for (int i = 0; i < numbones; i++)
{
TRS bone;
bone.translation = animationFrames[offset1 + i].translation * invt + animationFrames[offset2 + i].translation * t;
bone.rotation = animationFrames[offset1 + i].rotation * invt;
if ((bone.rotation | animationFrames[offset2 + i].rotation * t) < 0)
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)
{
bone.rotation.X *= -1; bone.rotation.Y *= -1; bone.rotation.Z *= -1; bone.rotation.W *= -1;
}
bone.rotation += animationFrames[offset2 + i].rotation * t;
bone.rotation += to.rotation * t;
bone.rotation.MakeUnit();
bone.scaling = animationFrames[offset1 + i].scaling * invt + animationFrames[offset2 + i].scaling * t;
bone.scaling = from.scaling * invt + to.scaling * t;
if (actor->boneComponentData->trscomponents[i].Equals(bone))
{

View File

@ -701,6 +701,16 @@ public:
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);
@ -1098,6 +1108,7 @@ public:
double FloatSpeed;
TObjPtr<DActorModelData*> modelData;
TObjPtr<DBoneComponents*> boneComponentData;
TObjPtr<DBoneManipulations*> boneManipulationData;
// interaction info
FBlockNode *BlockNode; // links in blocks (if needed)

View File

@ -5195,3 +5195,86 @@ DEFINE_ACTION_FUNCTION(AActor, GetRenderStyle)
}
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)
{
double cr = cos(rotationZ * 0.5);
double sr = sin(rotationZ * 0.5);
double cp = cos(rotationY * 0.5);
double sp = sin(rotationY * 0.5);
double cy = cos(rotationX * 0.5);
double sy = sin(rotationX * 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,6 +160,7 @@ 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)
@ -176,6 +177,7 @@ IMPLEMENT_POINTERS_START(AActor)
IMPLEMENT_POINTER(ViewPos)
IMPLEMENT_POINTER(modelData)
IMPLEMENT_POINTER(boneComponentData)
IMPLEMENT_POINTER(boneManipulationData)
IMPLEMENT_POINTERS_END
AActor::~AActor ()

View File

@ -1134,6 +1134,7 @@ 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,6 +373,12 @@ enum ChangeModelFlags
CMDL_USESURFACESKIN = 1 << 2,
};
// Manipulate Bone Flags
enum ManipulateBoneFlags
{
BM_USEEULER = 1
};
// Activation flags
enum EActivationFlags
{