Bone Getters Part 2/3, plus fixed warnings for MSVC

* add getters for frame poses

* fix missing joint in GetJointPose

* clean up models_iqm.cpp

* clean up usage of I_GetTimeFrac, split out matrix calculation into its own function

* clean up SetModelBoneRotationInternal

* clean up a few float <-> double and unsigned <-> signed warnings

* fix more warnings

* further clean up warnings

* split mode ObjectToWorldMatrix stuff

* initial work on bone getters, matrix hell

(the matrix/vec3 multiplications are probably wrong af, just gotta add more stuff 'till i can test it)

* clean up matrix math

* GetBone/TransformByBone

* fix GetBoneFramePose

* fix ObjectToWorldMatrix

* fix missing array resize

* raw matrix getters (for use with gutamatics/etc)

* reverse matrix mult order

* replace GetBoneLength/GetBoneDir with GetBoneBaseTRS

* fix GetBonePosition, remove GetBoneWorldMatrix as it's useless

* GetBonePosition

* deduplicate code

* rename GetBonePosition to GetBoneBasePosition to avoid confusion

* GetBoneBaseRotation

* GetBonePosition helper function

* forgot include_offsets
This commit is contained in:
Ricardo Luís Vaz Silva 2025-05-09 17:06:16 -03:00 committed by GitHub
commit 9e2b1f9c4c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 1109 additions and 261 deletions

View file

@ -101,6 +101,7 @@
#include "fragglescript/t_fs.h"
#include "shadowinlines.h"
#include "model.h"
#include "models.h"
#include "d_net.h"
// MACROS ------------------------------------------------------------------
@ -4244,6 +4245,122 @@ DEFINE_ACTION_FUNCTION(AActor, CheckPortalTransition)
return 0;
}
void AActor::CalcBones(bool recalc)
{
if(modelData && (!recalc || (modelData->flags & MODELDATA_GET_BONE_INFO_RECALC)) && modelData->flags & MODELDATA_GET_BONE_INFO)
{
if(picnum.isValid()) return; // picnum overrides don't render models
FSpriteModelFrame *smf = FindModelFrame(this, sprite, frame, false); // dropped flag is for voxels
if(!smf) return;
bool is_decoupled = flags9 & MF9_DECOUPLEDANIMATIONS;
double tic = Level->totaltime + 1;
CalcModelFrameInfo frameinfo = CalcModelFrame(Level, smf, state, tics, modelData, this, is_decoupled, tic, 1.0);
ModelDrawInfo drawinfo;
int boneStartingPosition = -1;
bool evaluatedSingle = false;
modelData->modelBoneInfo.Resize(frameinfo.modelsamount);
for (unsigned i = 0; i < frameinfo.modelsamount; i++)
{
if (CalcModelOverrides(i, smf, modelData, frameinfo, drawinfo, is_decoupled))
{
if(!evaluatedSingle)
{ // [Jay] TODO per-model decoupled animations
FModel * mdl = Models[drawinfo.modelid];
bool nextFrame = frameinfo.smfNext && drawinfo.modelframe != drawinfo.modelframenext;
ProcessModelFrame(mdl, nextFrame, i, smf, modelData, frameinfo, drawinfo, is_decoupled, tic, &modelData->modelBoneInfo[i]);
if(frameinfo.smf_flags & MDL_MODELSAREATTACHMENTS || is_decoupled)
{
evaluatedSingle = true;
//if(!is_decoupled) break;
break; // TODO remove this break when per-model decoupled animations are in
}
}
}
}
}
}
TRS AActor::GetBoneTRS(int model_index, int bone_index, bool with_override)
{
if(modelData && (modelData->flags & MODELDATA_GET_BONE_INFO) && model_index > 0 && bone_index > 0 && modelData->modelBoneInfo.SSize() < model_index && modelData->modelBoneInfo[model_index].bones.SSize() < bone_index)
{
return with_override ? modelData->modelBoneInfo[model_index].bones_with_override[bone_index] : modelData->modelBoneInfo[model_index].bones[bone_index];
}
return {};
}
void AActor::GetBoneMatrix(int model_index, int bone_index, bool with_override, double *outMat)
{
VSMatrix boneMatrix = (with_override ? modelData->modelBoneInfo[model_index].positions_with_override : modelData->modelBoneInfo[model_index].positions)[bone_index];
for(int i = 0; i < 16; i++)
{
outMat[i] = boneMatrix.mMatrix[i];
}
}
void AActor::GetBonePosition(int model_index, int bone_index, bool with_override, DVector3 &pos, DVector3 &normal)
{
if(modelData && modelData->flags & MODELDATA_GET_BONE_INFO)
{
if(picnum.isValid()) return; // picnum overrides don't render models
FSpriteModelFrame *smf = FindModelFrame(this, sprite, frame, false); // dropped flag is for voxels
FVector3 objPos = FVector3(Pos() + WorldOffset);
VSMatrix boneMatrix = (with_override ? modelData->modelBoneInfo[model_index].positions_with_override : modelData->modelBoneInfo[model_index].positions)[bone_index];
VSMatrix worldMatrix = smf->ObjectToWorldMatrix(this, objPos.X, objPos.Y, objPos.Z, 1.0);
FVector4 oldPos(pos.X, pos.Z, pos.Y, 1.0);
FVector4 newPos;
FVector4 oldNormal(normal.X, normal.Z, normal.Y, 0.0);
FVector4 newNormal;
boneMatrix.multMatrixPoint(&oldPos.X, &newPos.X);
boneMatrix.multMatrixPoint(&oldNormal.X, &newNormal.X);
oldPos = FVector4(FVector3(newPos.X, newPos.Y, newPos.Z) / newPos.W, 1.0);
oldNormal = FVector4(FVector3(newNormal.X, newNormal.Y, newNormal.Z) / newNormal.W, 0.0);
worldMatrix.multMatrixPoint(&oldPos.X, &newPos.X);
worldMatrix.multMatrixPoint(&oldNormal.X, &newNormal.X);
pos = DVector3(newPos.X, newPos.Z, newPos.Y);
normal = DVector3(newNormal.X, newNormal.Z, newNormal.Y);
}
}
void AActor::GetObjectToWorldMatrix(double *outMat)
{
if(modelData && modelData->flags & MODELDATA_GET_BONE_INFO)
{
if(picnum.isValid()) return; // picnum overrides don't render models
FSpriteModelFrame *smf = FindModelFrame(this, sprite, frame, false); // dropped flag is for voxels
FVector3 pos = FVector3(Pos() + WorldOffset);
VSMatrix outMatrix = smf->ObjectToWorldMatrix(this, pos.X, pos.Y, pos.Z, 1.0);
for(int i = 0; i < 16; i++)
{
outMat[i] = outMatrix.mMatrix[i];
}
}
}
//
// P_MobjThinker
//
@ -4291,6 +4408,11 @@ void AActor::Tick ()
return;
}
if(flags9 & MF9_DECOUPLEDANIMATIONS)
{
CalcBones(false);
}
AActor *onmo;
//assert (state != NULL);
@ -4852,6 +4974,11 @@ void AActor::Tick ()
}
}
if(!(flags9 & MF9_DECOUPLEDANIMATIONS) && modelData && !(modelData->flags & MODELDATA_GET_BONE_INFO_RECALC))
{
CalcBones(false);
}
if (tics == -1 || state->GetCanRaise())
{
int respawn_monsters = G_SkillProperty(SKILLP_Respawn);