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 Nash Muhandes
commit d5f5c71d67
33 changed files with 1065 additions and 220 deletions

View file

@ -307,7 +307,7 @@ bool Wiper_Crossfade::Run(int ticks)
bool Wiper_Crossfade::RunInterpolated(double ticks)
{
Clock += ticks;
Clock += float(ticks);
DrawTexture(twod, startScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE);
DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, DTA_Alpha, clamp(Clock / 32.f, 0.f, 1.f), TAG_DONE);
return Clock >= 32.;

View file

@ -157,6 +157,7 @@ public:
const char* GetHash() const { return Hash; }
int EntryCount() const { return NumLumps; }
uint32_t EntryCountU() const { return NumLumps; }
int FindEntry(const char* name);
size_t Length(uint32_t entry)

View file

@ -67,13 +67,13 @@ struct BoneOverrideComponent
void Modify(T &value, double tic) const
{
double lerp_amt = interplen > 0.0 ? std::clamp(((tic - switchtic) / interplen), 0.0, 1.0) : 1.0;
float lerp_amt = interplen > 0.0f ? std::clamp(float((tic - switchtic) / interplen), 0.0f, 1.0f) : 1.0f;
if(mode > 0 || (prev_mode > 0 && lerp_amt < 1.0))
{
T from = ModifyValue(value, prev, prev_mode);
T to = ModifyValue(value, cur, mode);
value = Lerp(from, to, lerp_amt, 1.0 - lerp_amt);
value = Lerp(from, to, lerp_amt, 1.0f - lerp_amt);
}
}
@ -126,9 +126,10 @@ struct BoneOverride
struct BoneInfo
{
TArray<TRS> bones_anim_only;
TArray<TRS> bones;
TArray<TRS> bones_with_override;
TArray<VSMatrix> positions;
TArray<VSMatrix> positions_with_override;
};
struct ModelAnim

View file

@ -17,7 +17,9 @@ class FGameTexture;
class IModelVertexBuffer;
class FModel;
class PClass;
class AActor;
struct FSpriteModelFrame;
struct FLevelLocals;
FTextureID LoadSkin(const char* path, const char* fn);
void FlushModels();
@ -59,6 +61,9 @@ public:
unsigned int getFlags(class DActorModelData * defs) const;
friend void InitModels();
friend void ParseModelDefLump(int Lump);
VSMatrix ObjectToWorldMatrix(AActor * actor, float x, float y, float z, double ticFrac);
VSMatrix ObjectToWorldMatrix(FLevelLocals *Level, DVector3 translation, DRotator rotation, DVector2 scaling, unsigned int flags, double tic);
};
@ -92,9 +97,12 @@ public:
virtual int FindJoint(FName name) { return -1; }
virtual int GetJointParent(int joint) { return -1; }
virtual double GetJointLength(int joint) { return 0.0; }
virtual FName GetJointName(int joint) { return NAME_None; }
virtual FVector3 GetJointDir(int joint) { return FVector3(0.0f,0.0f,0.0f); }
virtual FQuaternion GetJointRotation(int joint) { return FQuaternion(0.0f,0.0f,0.0f,1.0f); }
virtual FVector3 GetJointPosition(int joint) { return FVector3(0.0f,0.0f,0.0f); }
virtual TRS GetJointBaseTRS(int joint) { return {}; }
virtual TRS GetJointPose(int joint, int frame) { return {}; }
virtual int NumFrames() { return -1; }
virtual void GetJointChildren(int joint, TArray<int> &out) {}

View file

@ -73,6 +73,9 @@ struct IQMJoint
FVector3 Translate;
FQuaternion Quaternion;
FVector3 Scale;
FVector3 Position;
FQuaternion Rotation;
FVector3 Scaling;
};
struct IQMPose
@ -164,7 +167,7 @@ private:
TArray<VSMatrix> inversebaseframe;
TArray<TRS> TRSData;
public:
int NumJoints() override { return Joints.Size(); }
int NumJoints() override { return Joints.SSize(); }
int FindJoint(FName name) override
{
int *j = NamedJoints.CheckKey(name);
@ -174,12 +177,12 @@ public:
int GetJointParent(int joint) override
{
return (joint >= 0 && joint < Joints.Size()) ? Joints[joint].Parent : -1;
return (joint >= 0 && joint < Joints.SSize()) ? Joints[joint].Parent : -1;
}
FName GetJointName(int joint) override
{
return (joint >= 0 && joint < Joints.Size()) ? Joints[joint].Name : FName(NAME_None);
return (joint >= 0 && joint < Joints.SSize()) ? Joints[joint].Name : FName(NAME_None);
}
void GetRootJoints(TArray<int> &out) override
@ -189,20 +192,34 @@ public:
void GetJointChildren(int joint, TArray<int> &out) override
{
if(joint >= 0 && joint < Joints.Size())
if(joint >= 0 && joint < Joints.SSize())
{
out = Joints[joint].Children;
}
}
double GetJointLength(int joint) override
FQuaternion GetJointRotation(int joint) override
{
return (joint >= 0 && joint < Joints.Size()) ? Joints[joint].Translate.Length() : 0.0;
return (joint >= 0 && joint < Joints.SSize()) ? Joints[joint].Rotation : FQuaternion(0.0f,0.0f,0.0f,1.0f);
}
FVector3 GetJointDir(int joint) override
FVector3 GetJointPosition(int joint) override
{
return (joint >= 0 && joint < Joints.Size()) ? Joints[joint].Translate.Unit() : FVector3(0.0f,0.0f,0.0f);
return (joint >= 0 && joint < Joints.SSize()) ? Joints[joint].Position : FVector3(0.0f,0.0f,0.0f);
}
TRS GetJointBaseTRS(int joint) override
{
return (joint >= 0 && joint < Joints.SSize()) ? TRS{Joints[joint].Translate, Joints[joint].Quaternion, Joints[joint].Scale} : TRS{};
}
TRS GetJointPose(int joint, int frame) override
{
return (joint >= 0 && joint < Joints.SSize() && frame >= 0 && ((frame * Joints.SSize()) + joint) < TRSData.SSize()) ? TRSData[(frame * Joints.SSize()) + joint] : TRS{} ;
}
virtual int NumFrames()
{
return Joints.SSize() > 0 ? (TRSData.SSize() / Joints.SSize()) : 0;
}
};

View file

@ -108,7 +108,7 @@ bool IQMModel::Load(const char* path, int lumpnum, const char* buffer, int lengt
}
reader.SeekTo(ofs_joints);
for (int i = 0; i < Joints.Size(); i++)
for (int i = 0; i < Joints.SSize(); i++)
{
IQMJoint& joint = Joints[i];
@ -126,8 +126,6 @@ bool IQMModel::Load(const char* path, int lumpnum, const char* buffer, int lengt
joint.Translate.Y = reader.ReadFloat();
joint.Translate.Z = reader.ReadFloat();
int len = joint.Translate.Length();
joint.Quaternion.X = reader.ReadFloat();
joint.Quaternion.Y = reader.ReadFloat();
joint.Quaternion.Z = reader.ReadFloat();
@ -139,14 +137,24 @@ bool IQMModel::Load(const char* path, int lumpnum, const char* buffer, int lengt
if(joint.Parent < 0)
{
joint.Rotation = joint.Quaternion;
joint.Scaling = joint.Scale;
joint.Position = joint.Translate.ScaleXYZ(joint.Scaling);
RootJoints.Push(i);
}
else if(joint.Parent >= Joints.Size())
else if(joint.Parent >= i)
{
I_FatalError("Joint child comes before parent in IQM Model");
}
else if(joint.Parent >= Joints.SSize())
{
I_FatalError("Joint parent index out of bounds in IQM Model");
}
else
{
joint.Rotation = (Joints[joint.Parent].Rotation * joint.Quaternion).Unit();
joint.Scaling = joint.Scale.ScaleXYZ(Joints[joint.Parent].Scaling);
joint.Position = (Joints[joint.Parent].Rotation * joint.Translate.ScaleXYZ(joint.Scaling)) + Joints[joint.Parent].Position;
Joints[joint.Parent].Children.Push(i);
}
}
@ -618,11 +626,6 @@ const TArray<VSMatrix>* IQMModel::CalculateBones(const ModelAnimFrame &from, con
}
}
inline void ModifyBone(const BoneOverride& mod, TRS &bone, double time)
{
mod.Modify(bone, time);
}
// explicitly don't pass modelBoneOverrides when precalculating animation for interpolation, as it's applied _after_ animation
ModelAnimFramePrecalculatedIQM IQMModel::CalculateFrameIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray<TRS>* animationData)
{
@ -682,15 +685,16 @@ const TArray<VSMatrix>* IQMModel::CalculateBonesIQM(int frame1, int frame2, floa
{
const TArray<TRS>& animationFrames = animationData ? *animationData : TRSData;
TArray<VSMatrix>* outMatrix = out ? &out->positions : &boneData;
TArray<VSMatrix>* outMatrix = out ? &out->positions_with_override : &boneData;
int numbones = Joints.SSize();
outMatrix->Resize(numbones);
if(out)
{
out->bones_anim_only.Resize(numbones);
out->bones.Resize(numbones);
out->bones_with_override.Resize(numbones);
out->positions.Resize(numbones);
}
if(in && in->size() != Joints.Size()) in = nullptr;
@ -701,11 +705,11 @@ const TArray<VSMatrix>* IQMModel::CalculateBonesIQM(int frame1, int frame2, floa
frame1 = clamp(frame1, 0, (animationFrames.SSize() - 1) / numbones);
frame2 = clamp(frame2, 0, (animationFrames.SSize() - 1) / numbones);
int offset1 = frame1 * numbones;
int offset2 = frame2 * numbones;
unsigned int offset1 = frame1 * numbones;
unsigned int offset2 = frame2 * numbones;
int offset1_1 = frame1_prev * numbones;
int offset2_1 = frame2_prev * numbones;
unsigned int offset1_1 = frame1_prev * numbones;
unsigned int offset2_1 = frame2_prev * numbones;
float invt = 1.0f - inter;
float invt1 = 1.0f - inter1_prev;
@ -751,7 +755,7 @@ const TArray<VSMatrix>* IQMModel::CalculateBonesIQM(int frame1, int frame2, floa
if(out)
{
out->bones_anim_only[i] = bone;
out->bones[i] = bone;
if(in)
{
@ -774,7 +778,6 @@ const TArray<VSMatrix>* IQMModel::CalculateBonesIQM(int frame1, int frame2, floa
VSMatrix& result = (*outMatrix)[i];
if (Joints[i].Parent >= 0)
{
assert(Joints[i].Parent < i);
result = (*outMatrix)[Joints[i].Parent];
result.multMatrix(swapYZ);
result.multMatrix(baseframe[Joints[i].Parent]);
@ -788,6 +791,32 @@ const TArray<VSMatrix>* IQMModel::CalculateBonesIQM(int frame1, int frame2, floa
result.multMatrix(inversebaseframe[i]);
}
result.multMatrix(swapYZ);
if(out)
{
VSMatrix m;
m.loadIdentity();
m.translate(out->bones[i].translation.X, out->bones[i].translation.Y, out->bones[i].translation.Z);
m.multQuaternion(out->bones[i].rotation);
m.scale(out->bones[i].scaling.X, out->bones[i].scaling.Y, out->bones[i].scaling.Z);
VSMatrix& result = out->positions[i];
if (Joints[i].Parent >= 0)
{
result = out->positions[Joints[i].Parent];
result.multMatrix(swapYZ);
result.multMatrix(baseframe[Joints[i].Parent]);
result.multMatrix(m);
result.multMatrix(inversebaseframe[i]);
}
else
{
result.loadMatrix(swapYZ);
result.multMatrix(m);
result.multMatrix(inversebaseframe[i]);
}
result.multMatrix(swapYZ);
}
}
return &boneData;

View file

@ -680,14 +680,14 @@ int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction
auto vproto = Virtuals[i]->Proto;
auto &vflags = Virtuals[i]->ArgFlags;
int n = flags.size();
int n = flags.SSize();
bool flagsOk = true;
for(int i = 0; i < n; i++)
{
int argA = i >= vflags.size() ? 0 : vflags[i];
int argB = i >= flags.size() ? 0 : flags[i];
int argA = i >= vflags.SSize() ? 0 : vflags[i];
int argB = i >= flags.SSize() ? 0 : flags[i];
bool AisRef = argA & (VARF_Out | VARF_Ref);
bool BisRef = argB & (VARF_Out | VARF_Ref);

View file

@ -102,14 +102,14 @@ namespace
float v_MinimumToFill2(uint32_t inwidth, uint32_t inheight)
{
// sx = screen x dimension, sy = same for y
float sx = (float)inwidth * 1.2, sy = (float)inheight;
float sx = (float)inwidth * 1.2f, sy = (float)inheight;
static float lastsx = 0., lastsy = 0., result = 0.;
if (lastsx != sx || lastsy != sy)
{
if (sx <= 0. || sy <= 0.)
return 1.; // prevent x/0 error
// set absolute minimum scale to fill the entire screen but get as close to 640x400 as possible
float ssx = (float)(VID_MIN_UI_WIDTH) / 1.2 / sx, ssy = (float)(VID_MIN_UI_HEIGHT) / sy;
float ssx = (float)(VID_MIN_UI_WIDTH) / 1.2f / sx, ssy = (float)(VID_MIN_UI_HEIGHT) / sy;
result = (ssx < ssy) ? ssy : ssx;
lastsx = sx;
lastsy = sy;
@ -165,7 +165,7 @@ namespace
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return 1280; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 800; }, 1.2f, false }, // 4 - 1280x800
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customwidth; }, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customheight; }, 1.0f, true }, // 5 - Custom
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return 320; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 200; }, 1.2f, false }, // 6 - 320x200
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX2(Width, Height) * 1.2; }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY2(Width, Height); }, 1.2f, false }, // 7 - Minimum Scale to Fill Entire Screen (1.2)
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return uint32_t(v_mfillX2(Width, Height) * 1.2); }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY2(Width, Height); }, 1.2f, false }, // 7 - Minimum Scale to Fill Entire Screen (1.2)
};
bool isOutOfBounds(int x)
{

View file

@ -49,6 +49,7 @@
#endif
#include "m_png.h"
#include "basics.h"
#include "printf.h"
// MACROS ------------------------------------------------------------------
@ -944,7 +945,13 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
y = height;
stream.next_out = buffer.data();
stream.avail_out = buffer.size();
if(buffer.size() > UINT_MAX)
{
I_Error("save png buffer too large");
}
stream.avail_out = (unsigned int) buffer.size();
temprow[0][0] = 0;
#if USE_FILTER_HEURISTIC
@ -1006,12 +1013,24 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
}
while (stream.avail_out == 0)
{
if (!WriteIDAT (file, buffer.data(), buffer.size()))
if(buffer.size() > INT_MAX)
{
I_Error("save png buffer too large");
}
int sz = (int) buffer.size();
if (!WriteIDAT (file, buffer.data(), sz))
{
return false;
}
stream.next_out = buffer.data();
stream.avail_out = buffer.size();
if(buffer.size() > UINT_MAX)
{
I_Error("save png buffer too large");
}
stream.avail_out = (unsigned int) buffer.size();
if (stream.avail_in != 0)
{
err = deflate (&stream, (y == 0) ? Z_FINISH : 0);
@ -1032,12 +1051,23 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
}
if (stream.avail_out == 0)
{
if (!WriteIDAT (file, buffer.data(), buffer.size()))
if(buffer.size() > INT_MAX)
{
I_Error("save png buffer too large");
}
int sz = (int) buffer.size();
if (!WriteIDAT (file, buffer.data(), sz))
{
return false;
}
stream.next_out = buffer.data();
stream.avail_out = buffer.size();
if(buffer.size() > UINT_MAX)
{
I_Error("save png buffer too large");
}
stream.avail_out = (unsigned int) buffer.size();
}
}
@ -1047,7 +1077,15 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
{
return false;
}
return WriteIDAT (file, buffer.data(), buffer.size() - stream.avail_out);
if((buffer.size() - stream.avail_out) > INT_MAX)
{
I_Error("save png buffer too large");
}
int sz = (int) (buffer.size() - stream.avail_out);
return WriteIDAT (file, buffer.data(), sz);
}
//==========================================================================

View file

@ -144,7 +144,7 @@ class VSMatrix {
static void multMatrix(FLOATTYPE *resMatrix, const FLOATTYPE *aMatrix);
static void setIdentityMatrix(FLOATTYPE *mat, int size = 4);
public:
/// The storage for matrices
FLOATTYPE mMatrix[16];

View file

@ -82,25 +82,15 @@ public:
}
// returns the XY fields as a 2D-vector.
const Vector2& XY() const
Vector2 XY() const
{
return *reinterpret_cast<const Vector2*>(this);
return Vector2(X, Y);
}
Vector2& XY()
// returns the XYZ fields as a 3D-vector.
Vector3 XYZ() const
{
return *reinterpret_cast<Vector2*>(this);
}
// returns the XY fields as a 2D-vector.
const Vector3& XYZ() const
{
return *reinterpret_cast<const Vector3*>(this);
}
Vector3& XYZ()
{
return *reinterpret_cast<Vector3*>(this);
return Vector3(X, Y, Z);
}
@ -320,7 +310,10 @@ public:
auto factor = sinTheta / g_sqrt(lengthSquared);
TQuaternion<vec_t> ret;
ret.W = cosTheta;
ret.XYZ() = factor * axis;
auto xyz = vec_t(factor) * axis;
ret.X = vec_t(xyz.X);
ret.Y = vec_t(xyz.Y);
ret.Z = vec_t(xyz.Z);
return ret;
}
static TQuaternion<vec_t> FromAngles(TAngle<vec_t> yaw, TAngle<vec_t> pitch, TAngle<vec_t> roll)

View file

@ -705,12 +705,16 @@ struct TVector3
return *this;
}
// returns a version with swapped Z/Y
constexpr const TVector3 ToXZY() const
{
return {X, Z, Y};
}
constexpr TVector3 ScaleXYZ (const TVector3 &scaling)
{
return TVector3(X * scaling.X, Y * scaling.Y, Z * scaling.Z);
}
};
template<class vec_t>

View file

@ -1844,12 +1844,15 @@ FExecList *D_MultiExec (FArgs *list, FExecList *exec)
static void GetCmdLineFiles(std::vector<std::string>& wadfiles)
{
FString *args;
int i, argc;
int i;
int argc;
argc = Args->CheckParmList("-file", &args);
assert(wadfiles.size() < INT_MAX);
// [RL0] Check for array size to only add new wads
for (i = wadfiles.size(); i < argc; ++i)
for (i = int(wadfiles.size()); i < argc; ++i)
{
D_AddWildFile(wadfiles, args[i].GetChars(), ".wad", GameConfig);
}

View file

@ -123,7 +123,12 @@ void DNetworkBuffer::AddDouble(double msg)
void DNetworkBuffer::AddString(const FString& msg)
{
_size += msg.Len() + 1u;
if(msg.Len() >= UINT_MAX)
{
I_Error("network buffer string too large");
}
_size += ((unsigned int)msg.Len()) + 1u;
_buffer.Push({ NET_STRING, msg });
}
@ -427,8 +432,14 @@ bool EventManager::SendNetworkCommand(const FName& cmd, VMVa_List& args)
{
++bytes; // Strings will always consume at least one byte.
const FString* str = ListGetString(args);
if(str->Len() >= UINT_MAX || (bytes + (unsigned int)str->Len()) >= UINT_MAX)
{
I_Error("network buffer string too large");
}
if (str != nullptr)
bytes += str->Len();
bytes += (unsigned int)str->Len();
break;
}
}

View file

@ -2024,7 +2024,7 @@ void G_ReadSnapshots(FResourceFile *resf)
G_ClearSnapshots();
for (unsigned j = 0; j < resf->EntryCount(); j++)
for (unsigned j = 0; j < resf->EntryCountU(); j++)
{
auto name = resf->getName(j);
auto ptr = strstr(name, ".map.json");

View file

@ -1063,7 +1063,7 @@ public:
void SetPlaneReflectivity(int pos, double val)
{
reflect[pos] = val;
reflect[pos] = float(val);
}
double GetPlaneReflectivity(int pos)

View file

@ -210,7 +210,7 @@ void FTextureAnimator::InitAnimated (void)
if (lumpnum != -1)
{
auto animatedlump = fileSystem.ReadFile (lumpnum);
int animatedlen = fileSystem.FileLength(lumpnum);
ptrdiff_t animatedlen = fileSystem.FileLength(lumpnum);
auto animdefs = animatedlump.bytes();
const uint8_t *anim_p;
FTextureID pic1, pic2;

View file

@ -283,7 +283,12 @@ void InitBuildTiles()
}
auto& artdata = TexMan.GetNewBuildTileData();
artdata.Resize(fileSystem.FileLength(lumpnum));
ptrdiff_t len = fileSystem.FileLength(lumpnum);
assert(len >= 0 && len < UINT_MAX);
artdata.Resize((unsigned int)len);
fileSystem.ReadFile(lumpnum, &artdata[0]);
if ((numtiles = CountTiles(&artdata[0])) > 0)

View file

@ -93,7 +93,7 @@ SettingsPage::SettingsPage(LauncherWindow* launcher, int* autoloadflags) : Widge
}
}
}
catch (const std::exception& ex)
catch (const std::exception&)
{
hideLanguage = true;
}

View file

@ -283,7 +283,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck)
map->MapLumps[0].Reader = map->resource->GetEntryReader(0, FileSys::READER_SHARED);
uppercopy(map->MapLumps[0].Name, map->resource->getName(0));
for(uint32_t i = 1; i < map->resource->EntryCount(); i++)
for(uint32_t i = 1; i < map->resource->EntryCountU(); i++)
{
const char* lumpname = map->resource->getName(i);

View file

@ -726,8 +726,19 @@ struct AnimModelOverride
enum EModelDataFlags
{
MODELDATA_HADMODEL = 1 << 0,
MODELDATA_OVERRIDE_FLAGS = 1 << 1,
MODELDATA_HADMODEL = 1 << 0,
MODELDATA_OVERRIDE_FLAGS = 1 << 1,
MODELDATA_GET_BONE_INFO = 1 << 2,
MODELDATA_GET_BONE_INFO_RECALC = 1 << 3, // RECALCULATE BONE INFO INSTANTLY WHEN STATE/ANIMATION CHANGES, MIGHT GET EXPENSIVE
MODELDATA_IQMFLAGS = MODELDATA_GET_BONE_INFO | MODELDATA_GET_BONE_INFO_RECALC,
};
class DActorModelData : public DObject
@ -740,6 +751,7 @@ public:
TArray<AnimModelOverride> animationIDs;
TArray<int> modelFrameGenerators;
TArray<TArray<BoneOverride>> modelBoneOverrides;
TArray<BoneInfo> modelBoneInfo;
int flags;
int overrideFlagsSet;
int overrideFlagsClear;
@ -801,6 +813,15 @@ public:
virtual void Tick() override;
void EnableNetworking(const bool enable) override;
void CalcBones(bool recalc);
TRS GetBoneTRS(int model_index, int bone_index, bool with_override);
//outmat must be double[16]
void GetBoneMatrix(int model_index, int bone_index, bool with_override, double *outMat);
void GetBonePosition(int model_index, int bone_index, bool with_override, DVector3 &pos, DVector3 &normal);
void GetObjectToWorldMatrix(double *outMat);
static AActor *StaticSpawn (FLevelLocals *Level, PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing = false);
inline AActor *GetDefault () const

View file

@ -5125,15 +5125,6 @@ static void CleanupModelData(AActor * mobj)
FQuaternion InterpolateQuat(const FQuaternion &from, const FQuaternion &to, float t, float invt);
static void SetModelBoneRotationInternal(AActor * self, FModel * mdl, int model_index, int index, FQuaternion rotation, int mode, double interpolation_duration, double switchTic)
{
if(self->modelData->modelBoneOverrides.Size() <= model_index) self->modelData->modelBoneOverrides.Resize(model_index + 1);
self->modelData->modelBoneOverrides[model_index].Resize(mdl->NumJoints());
self->modelData->modelBoneOverrides[model_index][index].rotation.Set(rotation, switchTic, interpolation_duration, mode);
}
template<bool isSet, bool isOffset>
FModel * SetGetBoneShared(AActor * self, int model_index)
{
@ -5149,11 +5140,11 @@ FModel * SetGetBoneShared(AActor * self, int model_index)
EnsureModelData(self);
if(self->modelData->models.Size() > model_index && self->modelData->models[model_index].modelID >= 0 && self->modelData->models[model_index].modelID < Models.Size())
if(self->modelData->models.SSize() > model_index && self->modelData->models[model_index].modelID >= 0 && self->modelData->models[model_index].modelID < Models.SSize())
{
return Models[self->modelData->models[model_index].modelID];
}
else if(BaseSpriteModelFrames[self->GetClass()].modelIDs.Size() > model_index)
else if(BaseSpriteModelFrames[self->GetClass()].modelIDs.SSize() > model_index)
{
return Models[BaseSpriteModelFrames[self->GetClass()].modelIDs[model_index]];
}
@ -5182,7 +5173,7 @@ FModel * SetGetBoneSharedIndex(AActor * self, int model_index, int &bone_index,
ThrowAbortException(X_OTHER, "bone index out of range");
}
if(self->modelData->modelBoneOverrides.Size() <= model_index) self->modelData->modelBoneOverrides.Resize(model_index + 1);
if(self->modelData->modelBoneOverrides.SSize() <= model_index) self->modelData->modelBoneOverrides.Resize(model_index + 1);
self->modelData->modelBoneOverrides[model_index].Resize(mdl->NumJoints());
@ -5224,6 +5215,8 @@ static void SetModelBoneRotationNative(AActor * self, int model_index, int bone_
if(!mdl) return;
self->modelData->modelBoneOverrides[model_index][bone_index].rotation.Set(FQuaternion(rot_x, rot_y, rot_z, rot_w), self->Level->totaltime + ticFrac, interpolation_duration, mode);
self->CalcBones(true);
}
static void SetBoneRotationNative(AActor * self, int bone_index, double rot_x, double rot_y, double rot_z, double rot_w, int mode, double interpolation_duration, double ticFrac)
@ -5242,6 +5235,8 @@ static void SetModelNamedBoneRotationNative(AActor * self, int model_index, int
if(!mdl) return;
self->modelData->modelBoneOverrides[model_index][bone_index].rotation.Set(FQuaternion(rot_x, rot_y, rot_z, rot_w), self->Level->totaltime + ticFrac, interpolation_duration, mode);
self->CalcBones(true);
}
static void SetNamedBoneRotationNative(AActor * self, int boneName_i, double rot_x, double rot_y, double rot_z, double rot_w, int mode, double interpolation_duration, double ticFrac)
@ -5294,6 +5289,8 @@ static void SetModelBoneTranslationNative(AActor * self, int model_index, int bo
if(!mdl) return;
self->modelData->modelBoneOverrides[model_index][bone_index].translation.Set(FVector3(rot_x, rot_y, rot_z), self->Level->totaltime + ticFrac, interpolation_duration, mode);
self->CalcBones(true);
}
static void SetBoneTranslationNative(AActor * self, int bone_index, double rot_x, double rot_y, double rot_z, int mode, double interpolation_duration, double ticFrac)
@ -5312,6 +5309,8 @@ static void SetModelNamedBoneTranslationNative(AActor * self, int model_index, i
if(!mdl) return;
self->modelData->modelBoneOverrides[model_index][bone_index].translation.Set(FVector3(rot_x, rot_y, rot_z), self->Level->totaltime + ticFrac, interpolation_duration, mode);
self->CalcBones(true);
}
static void SetNamedBoneTranslationNative(AActor * self, int boneName_i, double rot_x, double rot_y, double rot_z, int mode, double interpolation_duration, double ticFrac)
@ -5362,6 +5361,8 @@ static void SetModelBoneScalingNative(AActor * self, int model_index, int bone_i
if(!mdl) return;
self->modelData->modelBoneOverrides[model_index][bone_index].scaling.Set(FVector3(rot_x, rot_y, rot_z), self->Level->totaltime + ticFrac, interpolation_duration, mode);
self->CalcBones(true);
}
static void SetBoneScalingNative(AActor * self, int bone_index, double rot_x, double rot_y, double rot_z, int mode, double interpolation_duration, double ticFrac)
@ -5380,6 +5381,8 @@ static void SetModelNamedBoneScalingNative(AActor * self, int model_index, int b
if(!mdl) return;
self->modelData->modelBoneOverrides[model_index][bone_index].scaling.Set(FVector3(rot_x, rot_y, rot_z), self->Level->totaltime + ticFrac, interpolation_duration, mode);
self->CalcBones(true);
}
static void SetNamedBoneScalingNative(AActor * self, int boneName_i, double rot_x, double rot_y, double rot_z, int mode, double interpolation_duration, double ticFrac)
@ -5665,51 +5668,46 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetNamedBoneChildren, GetNamedBoneChildren
return 0;
}
static double GetBoneLengthNative(AActor * self, int bone_index)
{
FModel * mdl = GetBoneShared(self, 0, bone_index, nullptr);
return mdl->GetJointLength(bone_index);
}
static double GetNamedBoneLengthNative(AActor * self, int boneName_i)
{
FName bone_name {ENamedName(boneName_i)};
int bone_index;
FModel * mdl = GetBoneShared(self, 0, bone_index, &bone_name);
return mdl->GetJointLength(bone_index);
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetBoneLength, GetBoneLengthNative)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(boneindex);
ACTION_RETURN_FLOAT(GetBoneLengthNative(self, boneindex));
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetNamedBoneLength, GetNamedBoneLengthNative)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_NAME(bonename);
ACTION_RETURN_FLOAT(GetNamedBoneLengthNative(self, bonename.GetIndex()));
}
DEFINE_ACTION_FUNCTION(AActor, GetBoneDir)
DEFINE_ACTION_FUNCTION(AActor, GetBoneBaseTRS)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(bone_index);
FModel * mdl = GetBoneShared(self, 0, bone_index, nullptr);
ACTION_RETURN_VEC3(DVector3(mdl->GetJointDir(bone_index)));
DVector3 translation(0,0,0);
DVector4 rotation(0,0,0,1);
DVector3 scaling(0,0,0);
if(mdl)
{
TRS pose = mdl->GetJointBaseTRS(bone_index);
translation = DVector3(pose.translation);
rotation = DVector4(pose.rotation);
scaling = DVector3(pose.scaling);
}
if(numret > 2)
{
ret[2].SetVector(scaling);
numret = 3;
}
if(numret > 1)
{
ret[1].SetVector(translation);
}
if(numret > 0)
{
ret[0].SetVector4(rotation);
}
return numret;
}
DEFINE_ACTION_FUNCTION(AActor, GetNamedBoneDir)
DEFINE_ACTION_FUNCTION(AActor, GetNamedBoneBaseTRS)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_NAME(bone_name);
@ -5718,7 +5716,36 @@ DEFINE_ACTION_FUNCTION(AActor, GetNamedBoneDir)
FModel * mdl = GetBoneShared(self, 0, bone_index, &bone_name);
ACTION_RETURN_VEC3(DVector3(mdl->GetJointDir(bone_index)));
DVector3 translation(0,0,0);
DVector4 rotation(0,0,0,1);
DVector3 scaling(0,0,0);
if(mdl)
{
TRS pose = mdl->GetJointBaseTRS(bone_index);
translation = DVector3(pose.translation);
rotation = DVector4(pose.rotation);
scaling = DVector3(pose.scaling);
}
if(numret > 2)
{
ret[2].SetVector(scaling);
numret = 3;
}
if(numret > 1)
{
ret[1].SetVector(translation);
}
if(numret > 0)
{
ret[0].SetVector4(rotation);
}
return numret;
}
static int GetBoneCountNative(AActor * self)
@ -5735,9 +5762,415 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetBoneCount, GetBoneCountNative)
ACTION_RETURN_INT(GetBoneCountNative(self));
}
//================================================
//
// Bone Pose Getters
//
//================================================
static int GetAnimStartFrameNative(AActor * self, int animName_i)
{
FName anim_name {ENamedName(animName_i)};
FModel * mdl = SetGetBoneShared<false, false>(self, 0);
return mdl->FindFirstFrame(anim_name);
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetAnimStartFrame, GetAnimStartFrameNative)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_NAME(animName);
ACTION_RETURN_INT(GetAnimStartFrameNative(self, animName.GetIndex()));
}
static int GetAnimEndFrameNative(AActor * self, int animName_i)
{
FName anim_name {ENamedName(animName_i)};
FModel * mdl = SetGetBoneShared<false, false>(self, 0);
return mdl->FindLastFrame(anim_name);
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetAnimEndFrame, GetAnimEndFrameNative)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_NAME(animName);
ACTION_RETURN_INT(GetAnimEndFrameNative(self, animName.GetIndex()));
}
static double GetAnimFramerateNative(AActor * self, int animName_i)
{
FName anim_name {ENamedName(animName_i)};
FModel * mdl = SetGetBoneShared<false, false>(self, 0);
return mdl->FindFramerate(anim_name);
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetAnimFramerate, GetAnimFramerateNative)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_NAME(animName);
ACTION_RETURN_FLOAT(GetAnimFramerateNative(self, animName.GetIndex()));
}
DEFINE_ACTION_FUNCTION(AActor, GetBoneFramePose)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(bone_index);
PARAM_INT(frame_index);
FModel * mdl = GetBoneShared(self, 0, bone_index, nullptr);
DVector3 translation(0,0,0);
DVector4 rotation(0,0,0,1);
DVector3 scaling(0,0,0);
if(mdl && frame_index < mdl->NumFrames())
{
TRS pose = mdl->GetJointPose(bone_index, frame_index);
translation = DVector3(pose.translation);
rotation = DVector4(pose.rotation);
scaling = DVector3(pose.scaling);
}
if(numret > 2)
{
ret[2].SetVector(scaling);
numret = 3;
}
if(numret > 1)
{
ret[1].SetVector(translation);
}
if(numret > 0)
{
ret[0].SetVector4(rotation);
}
return numret;
}
DEFINE_ACTION_FUNCTION(AActor, GetNamedBoneFramePose)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_NAME(bone_name);
PARAM_INT(frame_index);
int bone_index;
FModel * mdl = GetBoneShared(self, 0, bone_index, &bone_name);
DVector3 translation(0,0,0);
DVector4 rotation(0,0,0,1);
DVector3 scaling(0,0,0);
if(mdl && frame_index < mdl->NumFrames())
{
TRS pose = mdl->GetJointPose(bone_index, frame_index);
translation = DVector3(pose.translation);
rotation = DVector4(pose.rotation);
scaling = DVector3(pose.scaling);
}
if(numret > 2)
{
ret[2].SetVector(scaling);
numret = 3;
}
if(numret > 1)
{
ret[1].SetVector(translation);
}
if(numret > 0)
{
ret[0].SetVector4(rotation);
}
return numret;
}
DEFINE_ACTION_FUNCTION(AActor, GetBoneBasePosition)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(bone_index);
FModel * mdl = GetBoneShared(self, 0, bone_index, nullptr);
ACTION_RETURN_VEC3(DVector3(mdl->GetJointPosition(bone_index)));
}
DEFINE_ACTION_FUNCTION(AActor, GetNamedBoneBasePosition)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_NAME(bone_name);
int bone_index;
FModel * mdl = GetBoneShared(self, 0, bone_index, &bone_name);
ACTION_RETURN_VEC3(DVector3(mdl->GetJointPosition(bone_index)));
}
DEFINE_ACTION_FUNCTION(AActor, GetBoneBaseRotation)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(bone_index);
FModel * mdl = GetBoneShared(self, 0, bone_index, nullptr);
ACTION_RETURN_VEC4(DVector4(mdl->GetJointRotation(bone_index)));
}
DEFINE_ACTION_FUNCTION(AActor, GetNamedBoneBaseRotation)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_NAME(bone_name);
int bone_index;
FModel * mdl = GetBoneShared(self, 0, bone_index, &bone_name);
ACTION_RETURN_VEC4(DVector4(mdl->GetJointRotation(bone_index)));
}
//================================================
//
// Bone TRS Getters
//
//================================================
DEFINE_ACTION_FUNCTION(AActor, GetBone)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(bone_index);
PARAM_BOOL(with_override);
FModel * mdl = GetBoneShared(self, 0, bone_index, nullptr);
DVector3 translation(0,0,0);
DVector4 rotation(0,0,0,1);
DVector3 scaling(0,0,0);
if(mdl)
{
TRS trs = self->GetBoneTRS(0, bone_index, with_override);
translation = DVector3(trs.translation);
rotation = DVector4(trs.rotation);
scaling = DVector3(trs.scaling);
}
if(numret > 2)
{
ret[2].SetVector(scaling);
numret = 3;
}
if(numret > 1)
{
ret[1].SetVector(translation);
}
if(numret > 0)
{
ret[0].SetVector4(rotation);
}
return numret;
}
DEFINE_ACTION_FUNCTION(AActor, GetNamedBone)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_NAME(bone_name);
PARAM_BOOL(with_override);
int bone_index;
FModel * mdl = GetBoneShared(self, 0, bone_index, &bone_name);
DVector3 translation(0,0,0);
DVector4 rotation(0,0,0,1);
DVector3 scaling(0,0,0);
if(mdl)
{
TRS trs = self->GetBoneTRS(0, bone_index, with_override);
translation = DVector3(trs.translation);
rotation = DVector4(trs.rotation);
scaling = DVector3(trs.scaling);
}
if(numret > 2)
{
ret[2].SetVector(scaling);
numret = 3;
}
if(numret > 1)
{
ret[1].SetVector(translation);
}
if(numret > 0)
{
ret[0].SetVector4(rotation);
}
return numret;
}
DEFINE_ACTION_FUNCTION(AActor, TransformByBone)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(bone_index);
PARAM_FLOAT(pos_x);
PARAM_FLOAT(pos_y);
PARAM_FLOAT(pos_z);
PARAM_FLOAT(dir_x);
PARAM_FLOAT(dir_y);
PARAM_FLOAT(dir_z);
PARAM_BOOL(with_override);
FModel * mdl = GetBoneShared(self, 0, bone_index, nullptr);
DVector3 position(pos_x, pos_y, pos_z);
DVector3 direction(dir_x, dir_y, dir_z);
if(mdl)
{
self->GetBonePosition(0, bone_index, with_override, position, direction);
}
if(numret > 1)
{
ret[1].SetVector(direction);
}
if(numret > 0)
{
ret[0].SetVector(position);
}
return numret;
}
DEFINE_ACTION_FUNCTION(AActor, TransformByNamedBone)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_NAME(bone_name);
PARAM_FLOAT(pos_x);
PARAM_FLOAT(pos_y);
PARAM_FLOAT(pos_z);
PARAM_FLOAT(dir_x);
PARAM_FLOAT(dir_y);
PARAM_FLOAT(dir_z);
PARAM_BOOL(with_override);
int bone_index;
FModel * mdl = GetBoneShared(self, 0, bone_index, &bone_name);
DVector3 position(pos_x, pos_y, pos_z);
DVector3 direction(dir_x, dir_y, dir_z);
if(mdl)
{
self->GetBonePosition(0, bone_index, with_override, position, direction);
}
if(numret > 1)
{
ret[1].SetVector(direction);
}
if(numret > 0)
{
ret[0].SetVector(position);
}
return numret;
}
//================================================
//
// Bone Matrix Getters
//
//================================================
DEFINE_ACTION_FUNCTION(AActor, GetBoneMatrixRaw)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(bone_index);
PARAM_POINTER(outMatrix, TArray<double>);
PARAM_BOOL(with_override);
if(outMatrix)
{
FModel * mdl = GetBoneShared(self, 0, bone_index, nullptr);
outMatrix->Clear();
outMatrix->Resize(16);
if(mdl)
{
self->GetBoneMatrix(0, bone_index, with_override, outMatrix->Data());
}
}
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, GetNamedBoneMatrixRaw)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_NAME(bone_name);
PARAM_POINTER(outMatrix, TArray<double>);
PARAM_BOOL(with_override);
if(outMatrix)
{
int bone_index;
FModel * mdl = GetBoneShared(self, 0, bone_index, &bone_name);
outMatrix->Clear();
outMatrix->Resize(16);
if(mdl)
{
self->GetBoneMatrix(0, bone_index, with_override, outMatrix->Data());
}
}
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, GetObjectToWorldMatrixRaw)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_POINTER(outMatrix, TArray<double>);
if(outMatrix)
{
FModel * mdl = SetGetBoneShared<false, false>(self, 0);
outMatrix->Clear();
outMatrix->Resize(16);
if(mdl)
{
self->GetObjectToWorldMatrix(outMatrix->Data());
}
}
return 0;
}
//================================================
// SetAnimation
@ -5771,7 +6204,11 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
if(animName == NAME_None)
{
if(self->modelData->curAnim.flags & MODELANIM_NONE) return;
self->modelData->curAnim.flags = MODELANIM_NONE;
self->CalcBones(true);
return;
}
@ -5794,11 +6231,11 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
}
FModel * animation = nullptr;
if (animID >= 0 && animID < Models.Size())
if (animID >= 0 && animID < Models.SSize())
{
animation = Models[animID];
}
else if(self->modelData->models.Size() && self->modelData->models[0].modelID >= 0 && self->modelData->models[0].modelID < Models.Size())
else if(self->modelData->models.Size() > 0 && self->modelData->models[0].modelID >= 0 && self->modelData->models[0].modelID < Models.SSize())
{
animation = Models[self->modelData->models[0].modelID];
}
@ -5811,8 +6248,12 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
if(animStart == FErr_NotFound)
{
self->modelData->curAnim.flags = MODELANIM_NONE;
Printf("Could not find animation %s\n", animName.GetChars());
if(self->modelData->curAnim.flags & MODELANIM_NONE) return;
self->modelData->curAnim.flags = MODELANIM_NONE;
self->CalcBones(true);
return;
}
@ -5861,20 +6302,32 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
if(startFrame >= len)
{
self->modelData->curAnim.flags = MODELANIM_NONE;
Printf("frame %d (startFrame) is past the end of animation %s\n", startFrame, animName.GetChars());
if(self->modelData->curAnim.flags & MODELANIM_NONE) return;
self->modelData->curAnim.flags = MODELANIM_NONE;
self->CalcBones(true);
return;
}
else if(loopFrame >= len)
{
self->modelData->curAnim.flags = MODELANIM_NONE;
Printf("frame %d (loopFrame) is past the end of animation %s\n", startFrame, animName.GetChars());
if(self->modelData->curAnim.flags & MODELANIM_NONE) return;
self->modelData->curAnim.flags = MODELANIM_NONE;
self->CalcBones(true);
return;
}
else if(endFrame >= len)
{
self->modelData->curAnim.flags = MODELANIM_NONE;
Printf("frame %d (endFrame) is past the end of animation %s\n", endFrame, animName.GetChars());
if(self->modelData->curAnim.flags & MODELANIM_NONE) return;
self->modelData->curAnim.flags = MODELANIM_NONE;
self->CalcBones(true);
return;
}
@ -5896,6 +6349,8 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
self->modelData->curAnim.startTic = tic;
self->modelData->curAnim.switchOffset = 0;
}
self->CalcBones(true);
}
void SetAnimationNative(AActor * self, int i_animName, double framerate, int startFrame, int loopFrame, int endFrame, int interpolateTics, int flags)
@ -5957,29 +6412,60 @@ void SetAnimationFrameRateUINative(AActor * self, double framerate)
SetAnimationFrameRateInternal(self, framerate, I_GetTimeFrac());
}
void SetModelFlag(AActor * self, int flag)
void SetModelFlag(AActor * self, int flag, int iqmFlag)
{
EnsureModelData(self);
self->modelData->flags |= MODELDATA_OVERRIDE_FLAGS;
self->modelData->overrideFlagsSet |= flag;
self->modelData->overrideFlagsClear &= ~flag;
iqmFlag &= MODELDATA_IQMFLAGS;
if(flag)
{
self->modelData->flags |= MODELDATA_OVERRIDE_FLAGS;
self->modelData->overrideFlagsSet |= flag;
self->modelData->overrideFlagsClear &= ~flag;
}
if(iqmFlag)
{
self->modelData->flags |= iqmFlag;
}
}
void ClearModelFlag(AActor * self, int flag)
void ClearModelFlag(AActor * self, int flag, int iqmFlag)
{
EnsureModelData(self);
self->modelData->flags |= MODELDATA_OVERRIDE_FLAGS;
self->modelData->overrideFlagsClear |= flag;
self->modelData->overrideFlagsSet &= ~flag;
iqmFlag &= MODELDATA_IQMFLAGS;
if(flag)
{
self->modelData->flags |= MODELDATA_OVERRIDE_FLAGS;
self->modelData->overrideFlagsClear |= flag;
self->modelData->overrideFlagsSet &= ~flag;
}
if(iqmFlag)
{
self->modelData->flags &= ~iqmFlag;
}
}
void ResetModelFlags(AActor * self)
void ResetModelFlags(AActor * self, int resetModel, int resetIqm)
{
if(self->modelData)
{
self->modelData->overrideFlagsClear = 0;
self->modelData->overrideFlagsSet = 0;
self->modelData->flags &= ~MODELDATA_OVERRIDE_FLAGS;
if(resetModel)
{
self->modelData->overrideFlagsClear = 0;
self->modelData->overrideFlagsSet = 0;
self->modelData->flags &= ~MODELDATA_OVERRIDE_FLAGS;
}
if(resetIqm)
{
self->modelData->flags &= ~MODELDATA_IQMFLAGS;
}
}
}
@ -6148,6 +6634,11 @@ void ChangeModelNative(
CleanupModelData(mobj);
if(animation != NAME_None || modeldef != nullptr)
{
mobj->CalcBones(true);
}
return;
}
@ -6228,8 +6719,9 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetModelFlag, SetModelFlag)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(flag);
PARAM_INT(flagIqm);
SetModelFlag(self, flag);
SetModelFlag(self, flag, flagIqm);
return 0;
}
@ -6238,8 +6730,9 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, ClearModelFlag, ClearModelFlag)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(flag);
PARAM_INT(flagIqm);
ClearModelFlag(self, flag);
ClearModelFlag(self, flag, flagIqm);
return 0;
}
@ -6247,8 +6740,10 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, ClearModelFlag, ClearModelFlag)
DEFINE_ACTION_FUNCTION_NATIVE(AActor, ResetModelFlags, ResetModelFlags)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_BOOL(resetModel);
PARAM_BOOL(resetIqm);
ResetModelFlags(self);
ResetModelFlags(self, resetModel, resetIqm);
return 0;
}

View file

@ -1701,8 +1701,6 @@ int P_LookForTID (AActor *actor, INTBOOL allaround, FLookExParams *params)
AActor *LookForEnemiesInBlock (AActor *lookee, int index, void *extparam)
{
FBlockNode *block;
AActor *link;
AActor *other;
FLookExParams *params = (FLookExParams *)extparam;
for (block = lookee->Level->blockmap.blocklinks[index]; block != NULL; block = block->NextActor)

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 ------------------------------------------------------------------
@ -3898,6 +3899,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
//
@ -3945,6 +4062,11 @@ void AActor::Tick ()
return;
}
if(flags9 & MF9_DECOUPLEDANIMATIONS)
{
CalcBones(false);
}
AActor *onmo;
//assert (state != NULL);
@ -4501,6 +4623,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);

View file

@ -797,7 +797,7 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, GetSkin)
DEFINE_ACTION_FUNCTION(_PlayerInfo, GetSkinCount)
{
PARAM_SELF_STRUCT_PROLOGUE(player_t);
ACTION_RETURN_INT(Skins.size());
ACTION_RETURN_INT(Skins.SSize());
}
DEFINE_ACTION_FUNCTION(_PlayerInfo, GetGender)

View file

@ -61,32 +61,42 @@ float pauseTimeOffset = .0f;
extern TDeletingArray<FVoxel *> Voxels;
extern TDeletingArray<FVoxelDef *> VoxelDefs;
void RenderFrameModels(FModelRenderer* renderer, FLevelLocals* Level, const FSpriteModelFrame *smf, const FState* curState, const int curTics, FTranslationID translation, AActor* actor);
void RenderFrameModels(FModelRenderer* renderer, FLevelLocals* Level, const FSpriteModelFrame *smf, const FState* curState, int curTics, double tic, FTranslationID translation, AActor* actor);
void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor, double ticFrac)
{
// Setup transformation.
int smf_flags = smf->getFlags(actor->modelData);
FTranslationID translation = NO_TRANSLATION;
if (!(smf_flags & MDL_IGNORETRANSLATION))
translation = actor->Translation;
// y scale for a sprite means height, i.e. z in the world!
VSMatrix objectToWorldMatrix = smf->ObjectToWorldMatrix(actor, x, y, z, ticFrac);
float scaleFactorX = actor->Scale.X * smf->xscale;
float scaleFactorY = actor->Scale.X * smf->yscale;
float scaleFactorZ = actor->Scale.Y * smf->zscale;
float pitch = 0;
float roll = 0;
double rotateOffset = 0;
float orientation = scaleFactorX * scaleFactorY * scaleFactorZ;
renderer->BeginDrawModel(actor->RenderStyle, smf_flags, objectToWorldMatrix, orientation < 0);
RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, ticFrac, translation, actor);
renderer->EndDrawModel(actor->RenderStyle, smf_flags);
}
VSMatrix FSpriteModelFrame::ObjectToWorldMatrix(AActor * actor, float x, float y, float z, double ticFrac)
{
int smf_flags = getFlags(actor->modelData);
// Setup transformation.
DRotator angles;
if (actor->renderflags & RF_INTERPOLATEANGLES) // [Nash] use interpolated angles
angles = actor->InterpolatedAngles(ticFrac);
else
angles = actor->Angles;
float angle = angles.Yaw.Degrees();
float pitch = 0;
float roll = 0;
// [BB] Workaround for the missing pitch information.
if ((smf_flags & MDL_PITCHFROMMOMENTUM))
@ -109,34 +119,6 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
}
}
if (smf_flags & MDL_ROTATING)
{
bool isPaused = paused || P_CheckTickerPaused();
float timeFloat;
if (isPaused)
{
if (pauseTimeOffset == .0f)
pauseTimeOffset = (I_GetTime() + I_GetTimeFrac());
timeFloat = pauseTimeOffset;
}
else
{
pauseTimeOffset = .0f;
timeFloat = (I_GetTime() + I_GetTimeFrac());
}
if (smf->rotationSpeed > 0.0000000001 || smf->rotationSpeed < -0.0000000001)
{
double turns = timeFloat / (200.0 / smf->rotationSpeed);
turns -= floor(turns);
rotateOffset = turns * 360.0;
}
else
{
rotateOffset = 0.0;
}
}
// Added MDL_USEACTORPITCH and MDL_USEACTORROLL flags processing.
// If both flags MDL_USEACTORPITCH and MDL_PITCHFROMMOMENTUM are set, the pitch sums up the actor pitch and the velocity vector pitch.
if (smf_flags & MDL_USEACTORPITCH)
@ -147,75 +129,130 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
}
if (smf_flags & MDL_USEACTORROLL) roll += angles.Roll.Degrees();
// [Nash] take SpriteRotation into account
angle += actor->SpriteRotation.Degrees();
double tic = actor->Level->totaltime;
if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !actor->isFrozen())
{
tic += ticFrac;
}
return ObjectToWorldMatrix(actor->Level, DVector3(x, y, z), DRotator(DAngle::fromDeg(pitch), DAngle::fromDeg(angle), DAngle::fromDeg(roll)), actor->Scale, smf_flags, tic);
}
VSMatrix FSpriteModelFrame::ObjectToWorldMatrix(FLevelLocals *Level, DVector3 translation, DRotator rotation, DVector2 scaling, unsigned int flags, double tic)
{
double rotateOffset = 0;
if (flags & MDL_ROTATING)
{
bool isPaused = paused || P_CheckTickerPaused();
float timeFloat;
if (isPaused)
{
if (pauseTimeOffset == .0f)
pauseTimeOffset = tic;
timeFloat = pauseTimeOffset;
}
else
{
pauseTimeOffset = .0f;
timeFloat = tic;
}
if (rotationSpeed > 0.0000000001 || rotationSpeed < -0.0000000001)
{
double turns = (timeFloat) / (200.0 / rotationSpeed);
turns -= floor(turns);
rotateOffset = turns * 360.0;
}
else
{
rotateOffset = 0.0;
}
}
// y scale for a sprite means height, i.e. z in the world!
float scaleFactorX = scaling.X * xscale;
float scaleFactorY = scaling.X * yscale;
float scaleFactorZ = scaling.Y * zscale;
VSMatrix objectToWorldMatrix;
objectToWorldMatrix.loadIdentity();
// Model space => World space
objectToWorldMatrix.translate(x, z, y);
// [Nash] take SpriteRotation into account
angle += actor->SpriteRotation.Degrees();
objectToWorldMatrix.translate(translation.X, translation.Z, translation.Y);
// consider the pixel stretching. For non-voxels this must be factored out here
float stretch = 1.f;
// [MK] distortions might happen depending on when the pixel stretch is compensated for
// so we make the "undistorted" behavior opt-in
if (smf_flags & MDL_CORRECTPIXELSTRETCH)
if ((flags & MDL_CORRECTPIXELSTRETCH) && modelIDs.Size() > 0)
{
stretch = (smf->modelIDs[0] >= 0 ? Models[smf->modelIDs[0]]->getAspectFactor(actor->Level->info->pixelstretch) : 1.f) / actor->Level->info->pixelstretch;
stretch = (modelIDs[0] >= 0 ? Models[modelIDs[0]]->getAspectFactor(Level->info->pixelstretch) : 1.f) / Level->info->pixelstretch;
objectToWorldMatrix.scale(1, stretch, 1);
}
// Applying model transformations:
// 1) Applying actor angle, pitch and roll to the model
if (smf_flags & MDL_USEROTATIONCENTER)
if (flags & MDL_USEROTATIONCENTER)
{
objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterZ/stretch, smf->rotationCenterY);
}
objectToWorldMatrix.rotate(-angle, 0, 1, 0);
objectToWorldMatrix.rotate(pitch, 0, 0, 1);
objectToWorldMatrix.rotate(-roll, 1, 0, 0);
if (smf_flags & MDL_USEROTATIONCENTER)
{
objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterZ/stretch, -smf->rotationCenterY);
}
objectToWorldMatrix.translate(rotationCenterX, rotationCenterY/stretch, rotationCenterZ);
// 2) Applying Doomsday like rotation of the weapon pickup models
// The rotation angle is based on the elapsed time.
objectToWorldMatrix.rotate(-rotation.Yaw.Degrees(), 0, 1, 0);
objectToWorldMatrix.rotate(rotation.Pitch.Degrees(), 0, 0, 1);
objectToWorldMatrix.rotate(-rotation.Roll.Degrees(), 1, 0, 0);
if (smf_flags & MDL_ROTATING)
// 2) Applying Doomsday like rotation of the weapon pickup models
// The rotation angle is based on the elapsed time.
if(flags & MDL_ROTATING)
{
objectToWorldMatrix.rotate(rotateOffset, xrotate, yrotate, zrotate);
}
objectToWorldMatrix.translate(-rotationCenterX, -rotationCenterY/stretch, -rotationCenterZ);
}
else
{
objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterY/stretch, smf->rotationCenterZ);
objectToWorldMatrix.rotate(rotateOffset, smf->xrotate, smf->yrotate, smf->zrotate);
objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterY/stretch, -smf->rotationCenterZ);
objectToWorldMatrix.rotate(-rotation.Yaw.Degrees(), 0, 1, 0);
objectToWorldMatrix.rotate(rotation.Pitch.Degrees(), 0, 0, 1);
objectToWorldMatrix.rotate(-rotation.Roll.Degrees(), 1, 0, 0);
// 2) Applying Doomsday like rotation of the weapon pickup models
// The rotation angle is based on the elapsed time.
if(flags & MDL_ROTATING)
{
objectToWorldMatrix.translate(rotationCenterX, rotationCenterY/stretch, rotationCenterZ);
objectToWorldMatrix.rotate(rotateOffset, xrotate, yrotate, zrotate);
objectToWorldMatrix.translate(-rotationCenterX, -rotationCenterY/stretch, -rotationCenterZ);
}
}
// 3) Scaling model.
objectToWorldMatrix.scale(scaleFactorX, scaleFactorZ, scaleFactorY);
// 4) Aplying model offsets (model offsets do not depend on model scalings).
objectToWorldMatrix.translate(smf->xoffset / smf->xscale, smf->zoffset / (smf->zscale*stretch), smf->yoffset / smf->yscale);
objectToWorldMatrix.translate(xoffset / xscale, zoffset / (zscale*stretch), yoffset / yscale);
// 5) Applying model rotations.
objectToWorldMatrix.rotate(-smf->angleoffset, 0, 1, 0);
objectToWorldMatrix.rotate(smf->pitchoffset, 0, 0, 1);
objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0);
objectToWorldMatrix.rotate(-angleoffset, 0, 1, 0);
objectToWorldMatrix.rotate(pitchoffset, 0, 0, 1);
objectToWorldMatrix.rotate(-rolloffset, 1, 0, 0);
if (!(smf_flags & MDL_CORRECTPIXELSTRETCH) && smf->modelIDs.Size() > 0)
if (!(flags & MDL_CORRECTPIXELSTRETCH) && modelIDs.Size() > 0)
{
stretch = (smf->modelIDs[0] >= 0 ? Models[smf->modelIDs[0]]->getAspectFactor(actor->Level->info->pixelstretch) : 1.f) / actor->Level->info->pixelstretch;
stretch = (modelIDs[0] >= 0 ? Models[modelIDs[0]]->getAspectFactor(Level->info->pixelstretch) : 1.f) / Level->info->pixelstretch;
objectToWorldMatrix.scale(1, stretch, 1);
}
float orientation = scaleFactorX * scaleFactorY * scaleFactorZ;
renderer->BeginDrawModel(actor->RenderStyle, smf_flags, objectToWorldMatrix, orientation < 0);
RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, translation, actor);
renderer->EndDrawModel(actor->RenderStyle, smf_flags);
return objectToWorldMatrix;
}
void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translation, FVector3 rotation, FVector3 rotation_pivot, FSpriteModelFrame *smf)
void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translation, FVector3 rotation, FVector3 rotation_pivot, FSpriteModelFrame *smf, double ticFrac)
{
AActor * playermo = players[consoleplayer].camera;
@ -272,7 +309,7 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translatio
auto trans = psp->GetTranslation();
if ((psp->Flags & PSPF_PLAYERTRANSLATED)) trans = psp->Owner->mo->Translation;
RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), trans, psp->Caller);
RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), ticFrac, trans, psp->Caller);
renderer->EndDrawHUDModel(playermo->RenderStyle, smf_flags);
}
@ -329,7 +366,7 @@ void calcFrames(const ModelAnim &curAnim, double tic, ModelAnimFrameInterp &to,
}
}
CalcModelFrameInfo CalcModelFrame(FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, DActorModelData* data, AActor* actor, bool is_decoupled, double tic)
CalcModelFrameInfo CalcModelFrame(FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, DActorModelData* data, AActor* actor, bool is_decoupled, double tic, double ticFrac)
{
// [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation
// and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame.
@ -364,8 +401,9 @@ CalcModelFrameInfo CalcModelFrame(FLevelLocals *Level, const FSpriteModelFrame *
// [BB] In case the tic counter is frozen we have to leave ticFraction at zero.
if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !Level->isFrozen())
{
ticFraction = I_GetTimeFrac();
ticFraction = ticFrac;
}
inter = static_cast<double>(curState->Tics - curTics + ticFraction) / static_cast<double>(curState->Tics);
// [BB] For some actors (e.g. ZPoisonShroom) spr->actor->tics can be bigger than curState->Tics.
@ -429,11 +467,11 @@ bool CalcModelOverrides(int i, const FSpriteModelFrame *smf, DActorModelData* da
if (data)
{
//modelID
if (data->models.Size() > i && data->models[i].modelID >= 0)
if (data->models.SSize() > i && data->models[i].modelID >= 0)
{
out.modelid = data->models[i].modelID;
}
else if(data->models.Size() > i && data->models[i].modelID == -2)
else if(data->models.SSize() > i && data->models[i].modelID == -2)
{
return false;
}
@ -443,7 +481,7 @@ bool CalcModelOverrides(int i, const FSpriteModelFrame *smf, DActorModelData* da
}
//animationID
if (data->animationIDs.Size() > i && data->animationIDs[i] >= 0)
if (data->animationIDs.SSize() > i && data->animationIDs[i] >= 0)
{
out.animationid = data->animationIDs[i];
}
@ -454,7 +492,7 @@ bool CalcModelOverrides(int i, const FSpriteModelFrame *smf, DActorModelData* da
if(!is_decoupled)
{
//modelFrame
if (data->modelFrameGenerators.Size() > i
if (data->modelFrameGenerators.SSize() > i
&& (unsigned)data->modelFrameGenerators[i] < info.modelsamount
&& smf->modelframes[data->modelFrameGenerators[i]] >= 0
) {
@ -480,7 +518,7 @@ bool CalcModelOverrides(int i, const FSpriteModelFrame *smf, DActorModelData* da
}
//skinID
if (data->skinIDs.Size() > i && data->skinIDs[i].isValid())
if (data->skinIDs.SSize() > i && data->skinIDs[i].isValid())
{
out.skinid = data->skinIDs[i];
}
@ -490,7 +528,7 @@ bool CalcModelOverrides(int i, const FSpriteModelFrame *smf, DActorModelData* da
}
//surfaceSkinIDs
if(data->models.Size() > i && data->models[i].surfaceSkinIDs.Size() > 0)
if(data->models.SSize() > i && data->models[i].surfaceSkinIDs.SSize() > 0)
{
unsigned sz1 = smf->surfaceskinIDs.Size();
unsigned sz2 = data->models[i].surfaceSkinIDs.Size();
@ -550,7 +588,7 @@ const TArray<VSMatrix> * ProcessModelFrame(FModel * animation, bool nextFrame, i
frameinfo.decoupled_frame,
frameinfo.inter,
animationData,
modelData->modelBoneOverrides.Size() > i
modelData->modelBoneOverrides.SSize() > i
? &modelData->modelBoneOverrides[i]
: nullptr,
out,
@ -568,7 +606,7 @@ const TArray<VSMatrix> * ProcessModelFrame(FModel * animation, bool nextFrame, i
},
-1.0f,
animationData,
(modelData && modelData->modelBoneOverrides.Size() > i)
(modelData && modelData->modelBoneOverrides.SSize() > i)
? &modelData->modelBoneOverrides[i]
: nullptr,
out,
@ -586,7 +624,7 @@ static inline void RenderModelFrame(FModelRenderer *renderer, int i, const FSpri
auto ssidp = drawinfo.surfaceskinids.Size() > 0
? drawinfo.surfaceskinids.Data()
: (((i * MD3_MAX_SURFACES) < smf->surfaceskinIDs.Size()) ? &smf->surfaceskinIDs[i * MD3_MAX_SURFACES] : nullptr);
: (((i * MD3_MAX_SURFACES) < smf->surfaceskinIDs.SSize()) ? &smf->surfaceskinIDs[i * MD3_MAX_SURFACES] : nullptr);
bool nextFrame = frameinfo.smfNext && drawinfo.modelframe != drawinfo.modelframenext;
@ -605,19 +643,19 @@ static inline void RenderModelFrame(FModelRenderer *renderer, int i, const FSpri
mdl->RenderFrame(renderer, tex, drawinfo.modelframe, nextFrame ? drawinfo.modelframenext : drawinfo.modelframe, nextFrame ? frameinfo.inter : -1.f, translation, ssidp, boneStartingPosition, actor);
}
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, FTranslationID translation, AActor* actor)
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, int curTics, double ticFrac, FTranslationID translation, AActor* actor)
{
double tic = actor->Level->totaltime;
if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !actor->isFrozen())
{
tic += I_GetTimeFrac();
tic += ticFrac;
}
bool is_decoupled = (actor->flags9 & MF9_DECOUPLEDANIMATIONS);
DActorModelData* modelData = actor ? actor->modelData.ForceGet() : nullptr;
CalcModelFrameInfo frameinfo = CalcModelFrame(Level, smf, curState, curTics, modelData, actor, is_decoupled, tic);
CalcModelFrameInfo frameinfo = CalcModelFrame(Level, smf, curState, curTics, modelData, actor, is_decoupled, tic, ticFrac);
ModelDrawInfo drawinfo;
int boneStartingPosition = -1;

View file

@ -115,7 +115,7 @@ void BSPWalkCircle(FLevelLocals *Level, float x, float y, float radiusSquared, c
}
void RenderModel(FModelRenderer* renderer, float x, float y, float z, FSpriteModelFrame* smf, AActor* actor, double ticFrac);
void RenderHUDModel(FModelRenderer* renderer, DPSprite* psp, FVector3 translation, FVector3 rotation, FVector3 rotation_pivot, FSpriteModelFrame *smf);
void RenderHUDModel(FModelRenderer* renderer, DPSprite* psp, FVector3 translation, FVector3 rotation, FVector3 rotation_pivot, FSpriteModelFrame *smf, double ticFrac);
struct CalcModelFrameInfo
{
@ -140,7 +140,7 @@ struct ModelDrawInfo
class DActorModelData;
CalcModelFrameInfo CalcModelFrame(FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, DActorModelData* modelData, AActor* actor, bool is_decoupled, double tic);
CalcModelFrameInfo CalcModelFrame(FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, int curTics, DActorModelData* modelData, AActor* actor, bool is_decoupled, double tic, double ticFrac);
// returns true if the model isn't removed
bool CalcModelOverrides(int modelindex, const FSpriteModelFrame *smf, DActorModelData* modelData, const CalcModelFrameInfo &frameinfo, ModelDrawInfo &drawinfo, bool is_decoupled);

View file

@ -93,7 +93,7 @@ void HWDrawInfo::DrawPSprite(HUDSprite *huds, FRenderState &state)
state.AlphaFunc(Alpha_GEqual, 0);
FHWModelRenderer renderer(this, state, huds->lightindex);
RenderHUDModel(&renderer, huds->weapon, huds->translation, huds->rotation + FVector3(huds->mx / 4., (huds->my - WEAPONTOP) / -4., 0), huds->pivot, huds->mframe);
RenderHUDModel(&renderer, huds->weapon, huds->translation, huds->rotation + FVector3(huds->mx / 4., (huds->my - WEAPONTOP) / -4., 0), huds->pivot, huds->mframe, Viewpoint.TicFrac);
state.SetFlatVertexBuffer();
state.SetShadeVertex(false);
}

View file

@ -68,7 +68,7 @@
#include "i_interface.h"
#include "d_main.h"
const float MY_SQRT2 = 1.41421356237309504880; // sqrt(2)
const float MY_SQRT2 = float(1.41421356237309504880); // sqrt(2)
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern bool DrawFSHUD; // [RH] Defined in d_main.cpp

View file

@ -339,7 +339,7 @@ TArray<FString> I_GetSteamPath()
}
}
}
catch (const CRecoverableError& err)
catch (const CRecoverableError&)
{
// don't abort on errors in here. Just return an empty path.
}