From d5f5c71d67f69c4ee6c6fcb51691dafadfdf0861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Fri, 9 May 2025 17:06:16 -0300 Subject: [PATCH] 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 --- src/common/2d/wipe.cpp | 2 +- src/common/filesystem/include/resourcefile.h | 1 + src/common/models/bonecomponents.h | 7 +- src/common/models/model.h | 12 +- src/common/models/model_iqm.h | 33 +- src/common/models/models_iqm.cpp | 63 +- src/common/objects/dobjtype.cpp | 6 +- src/common/rendering/r_videoscale.cpp | 6 +- src/common/textures/m_png.cpp | 50 +- src/common/utility/matrix.h | 2 +- src/common/utility/quaternion.h | 25 +- src/common/utility/vectors.h | 6 +- src/d_main.cpp | 7 +- src/events.cpp | 15 +- src/g_level.cpp | 2 +- src/gamedata/r_defs.h | 2 +- src/gamedata/textures/animations.cpp | 2 +- src/gamedata/textures/buildloader.cpp | 7 +- src/launcher/settingspage.cpp | 2 +- src/p_openmap.cpp | 2 +- src/playsim/actor.h | 25 +- src/playsim/p_actionfunctions.cpp | 637 ++++++++++++++++--- src/playsim/p_enemy.cpp | 2 - src/playsim/p_mobj.cpp | 127 ++++ src/playsim/p_user.cpp | 2 +- src/r_data/models.cpp | 210 +++--- src/r_data/models.h | 4 +- src/rendering/hwrenderer/scene/hw_weapon.cpp | 2 +- src/rendering/r_utility.cpp | 2 +- src/win32/i_steam.cpp | 2 +- tools/lemon/lemon.c | 6 +- wadsrc/static/zscript/actors/actor.zs | 73 ++- wadsrc/static/zscript/constants.zs | 7 + 33 files changed, 1098 insertions(+), 253 deletions(-) diff --git a/src/common/2d/wipe.cpp b/src/common/2d/wipe.cpp index 3682070db..ff6b6879c 100644 --- a/src/common/2d/wipe.cpp +++ b/src/common/2d/wipe.cpp @@ -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.; diff --git a/src/common/filesystem/include/resourcefile.h b/src/common/filesystem/include/resourcefile.h index 3d2da11b0..b1730670d 100644 --- a/src/common/filesystem/include/resourcefile.h +++ b/src/common/filesystem/include/resourcefile.h @@ -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) diff --git a/src/common/models/bonecomponents.h b/src/common/models/bonecomponents.h index db8957f8a..de0f74856 100644 --- a/src/common/models/bonecomponents.h +++ b/src/common/models/bonecomponents.h @@ -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 bones_anim_only; + TArray bones; TArray bones_with_override; TArray positions; + TArray positions_with_override; }; struct ModelAnim diff --git a/src/common/models/model.h b/src/common/models/model.h index dcd066c55..7b768d21a 100644 --- a/src/common/models/model.h +++ b/src/common/models/model.h @@ -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 &out) {} diff --git a/src/common/models/model_iqm.h b/src/common/models/model_iqm.h index 6ab65c5d0..0581ef527 100644 --- a/src/common/models/model_iqm.h +++ b/src/common/models/model_iqm.h @@ -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 inversebaseframe; TArray 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 &out) override @@ -189,20 +192,34 @@ public: void GetJointChildren(int joint, TArray &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; } }; diff --git a/src/common/models/models_iqm.cpp b/src/common/models/models_iqm.cpp index 164639ffb..31f853114 100644 --- a/src/common/models/models_iqm.cpp +++ b/src/common/models/models_iqm.cpp @@ -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* 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* animationData) { @@ -682,15 +685,16 @@ const TArray* IQMModel::CalculateBonesIQM(int frame1, int frame2, floa { const TArray& animationFrames = animationData ? *animationData : TRSData; - TArray* outMatrix = out ? &out->positions : &boneData; + TArray* 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* 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* 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* 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* 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; diff --git a/src/common/objects/dobjtype.cpp b/src/common/objects/dobjtype.cpp index eac10469a..ace318b4c 100644 --- a/src/common/objects/dobjtype.cpp +++ b/src/common/objects/dobjtype.cpp @@ -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); diff --git a/src/common/rendering/r_videoscale.cpp b/src/common/rendering/r_videoscale.cpp index 51f2844d1..837886be9 100644 --- a/src/common/rendering/r_videoscale.cpp +++ b/src/common/rendering/r_videoscale.cpp @@ -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) { diff --git a/src/common/textures/m_png.cpp b/src/common/textures/m_png.cpp index 83714a6ac..d32083bb4 100644 --- a/src/common/textures/m_png.cpp +++ b/src/common/textures/m_png.cpp @@ -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); } //========================================================================== diff --git a/src/common/utility/matrix.h b/src/common/utility/matrix.h index e0317be4c..8e33cd20c 100644 --- a/src/common/utility/matrix.h +++ b/src/common/utility/matrix.h @@ -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]; diff --git a/src/common/utility/quaternion.h b/src/common/utility/quaternion.h index a1c506e6e..9f2af2619 100644 --- a/src/common/utility/quaternion.h +++ b/src/common/utility/quaternion.h @@ -82,25 +82,15 @@ public: } // returns the XY fields as a 2D-vector. - const Vector2& XY() const + Vector2 XY() const { - return *reinterpret_cast(this); + return Vector2(X, Y); } - Vector2& XY() + // returns the XYZ fields as a 3D-vector. + Vector3 XYZ() const { - return *reinterpret_cast(this); - } - - // returns the XY fields as a 2D-vector. - const Vector3& XYZ() const - { - return *reinterpret_cast(this); - } - - Vector3& XYZ() - { - return *reinterpret_cast(this); + return Vector3(X, Y, Z); } @@ -320,7 +310,10 @@ public: auto factor = sinTheta / g_sqrt(lengthSquared); TQuaternion 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 FromAngles(TAngle yaw, TAngle pitch, TAngle roll) diff --git a/src/common/utility/vectors.h b/src/common/utility/vectors.h index d901a7cc9..d14c24c3a 100644 --- a/src/common/utility/vectors.h +++ b/src/common/utility/vectors.h @@ -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 diff --git a/src/d_main.cpp b/src/d_main.cpp index f5ffeca81..32b50caed 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1844,12 +1844,15 @@ FExecList *D_MultiExec (FArgs *list, FExecList *exec) static void GetCmdLineFiles(std::vector& 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); } diff --git a/src/events.cpp b/src/events.cpp index a45bacd8b..80059b5e7 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -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; } } diff --git a/src/g_level.cpp b/src/g_level.cpp index 8bfa2c391..9af836035 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -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"); diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index 0091ed0e1..a9fba5174 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -1063,7 +1063,7 @@ public: void SetPlaneReflectivity(int pos, double val) { - reflect[pos] = val; + reflect[pos] = float(val); } double GetPlaneReflectivity(int pos) diff --git a/src/gamedata/textures/animations.cpp b/src/gamedata/textures/animations.cpp index 619375c46..d79e2bab7 100644 --- a/src/gamedata/textures/animations.cpp +++ b/src/gamedata/textures/animations.cpp @@ -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; diff --git a/src/gamedata/textures/buildloader.cpp b/src/gamedata/textures/buildloader.cpp index 83c547b50..a29cbb1e9 100644 --- a/src/gamedata/textures/buildloader.cpp +++ b/src/gamedata/textures/buildloader.cpp @@ -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) diff --git a/src/launcher/settingspage.cpp b/src/launcher/settingspage.cpp index 1bfe54d22..01b6817df 100644 --- a/src/launcher/settingspage.cpp +++ b/src/launcher/settingspage.cpp @@ -93,7 +93,7 @@ SettingsPage::SettingsPage(LauncherWindow* launcher, int* autoloadflags) : Widge } } } - catch (const std::exception& ex) + catch (const std::exception&) { hideLanguage = true; } diff --git a/src/p_openmap.cpp b/src/p_openmap.cpp index ef688cda6..0906f65ea 100644 --- a/src/p_openmap.cpp +++ b/src/p_openmap.cpp @@ -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); diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 9fdfa9694..b0ce878d4 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -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 animationIDs; TArray modelFrameGenerators; TArray> modelBoneOverrides; + TArray 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 diff --git a/src/playsim/p_actionfunctions.cpp b/src/playsim/p_actionfunctions.cpp index 98897d873..be5463bae 100644 --- a/src/playsim/p_actionfunctions.cpp +++ b/src/playsim/p_actionfunctions.cpp @@ -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 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(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(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(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); + 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); + 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); + + if(outMatrix) + { + FModel * mdl = SetGetBoneShared(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; } diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index 16a8918a4..0f69a57e0 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -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) diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index b256f756b..82db39595 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -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); diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 65f892903..3d4de076d 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -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) diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index 884886586..7badb92a0 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -61,32 +61,42 @@ float pauseTimeOffset = .0f; extern TDeletingArray Voxels; extern TDeletingArray 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(curState->Tics - curTics + ticFraction) / static_cast(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 * 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 * 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; diff --git a/src/r_data/models.h b/src/r_data/models.h index a62d59333..d421194e3 100644 --- a/src/r_data/models.h +++ b/src/r_data/models.h @@ -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); diff --git a/src/rendering/hwrenderer/scene/hw_weapon.cpp b/src/rendering/hwrenderer/scene/hw_weapon.cpp index ad957ea3c..ad3b64d8f 100644 --- a/src/rendering/hwrenderer/scene/hw_weapon.cpp +++ b/src/rendering/hwrenderer/scene/hw_weapon.cpp @@ -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); } diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index a1f6116f1..d93bb67c7 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -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 diff --git a/src/win32/i_steam.cpp b/src/win32/i_steam.cpp index 2cc76ab66..0c0512b07 100644 --- a/src/win32/i_steam.cpp +++ b/src/win32/i_steam.cpp @@ -339,7 +339,7 @@ TArray I_GetSteamPath() } } } - catch (const CRecoverableError& err) + catch (const CRecoverableError&) { // don't abort on errors in here. Just return an empty path. } diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index 45f458d72..2c229ba08 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -416,7 +416,7 @@ static int actioncmp(void *_ap1,void *_ap2) rc = ap1->x.rp->index - ap2->x.rp->index; } if( rc==0 ){ - rc = ap2 - ap1; + rc = (int)(ap2 - ap1); } return rc; } @@ -1957,7 +1957,7 @@ static int handleswitch(int i, FILE *err) if( err ){ fprintf(err, "%sillegal character in floating-point argument.\n",emsg); - errline(i,((size_t)end)-(size_t)argv[i],err); + errline(i,(int)(((size_t)end)-(size_t)argv[i]),err); } errcnt++; } @@ -1968,7 +1968,7 @@ static int handleswitch(int i, FILE *err) if( *end ){ if( err ){ fprintf(err,"%sillegal character in integer argument.\n",emsg); - errline(i,((size_t)end)-(size_t)argv[i],err); + errline(i,(int)(((size_t)end)-(size_t)argv[i]),err); } errcnt++; } diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 32127c669..48588bcb6 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -1408,17 +1408,67 @@ class Actor : Thinker native native version("4.15.1") void GetBoneChildren(int boneIndex, out Array children); native version("4.15.1") void GetNamedBoneChildren(Name boneName, out Array children); - - // this is the length in model units, not in world units, and does not take model scale in MODELDEF, world, etc, or current animation or offset into account at all - native version("4.15.1") double GetBoneLength(int boneIndex); - native version("4.15.1") double GetNamedBoneLength(Name boneName); - - // this is the direction of the bone in the armature, does not take the current animation or offset into account at all - native version("4.15.1") Vector3 GetBoneDir(int boneIndex); - native version("4.15.1") Vector3 GetNamedBoneDir(Name boneName); + /* rotation, translation, scaling */ + native version("4.15.1") Quat, Vector3, Vector3 GetBoneBaseTRS(int boneIndex); + native version("4.15.1") Quat, Vector3, Vector3 GetNamedBoneBaseTRS(Name boneName); + + native version("4.15.1") Vector3 GetBoneBasePosition(int boneIndex); + native version("4.15.1") Vector3 GetNamedBoneBasePosition(Name boneName); + + native version("4.15.1") Quat GetBoneBaseRotation(int boneIndex); + native version("4.15.1") Quat GetNamedBoneBaseRotation(Name boneName); + native version("4.15.1") int GetBoneCount(); + //================================================ + // + // Bone Pose Getters + // + //================================================ + + native version("4.15.1") int GetAnimStartFrame(Name animName); + native version("4.15.1") int GetAnimEndFrame(Name animName); + native version("4.15.1") double GetAnimFramerate(Name animName); + + /* rotation, translation, scaling */ + native version("4.15.1") Quat, Vector3, Vector3 GetBoneFramePose(int boneIndex, int frame); + native version("4.15.1") Quat, Vector3, Vector3 GetNamedBoneFramePose(Name boneName, int frame); + + //================================================ + // + // Bone TRS Getters + // + //================================================ + + /* rotation, translation, scaling */ + native version("4.15.1") Quat, Vector3, Vector3 GetBone(int boneIndex, bool include_offsets = true); + native version("4.15.1") Quat, Vector3, Vector3 GetNamedBone(Name boneName, bool include_offsets = true); + + native version("4.15.1") Vector3, Vector3 TransformByBone(int boneIndex, Vector3 position, Vector3 direction = (0,0,0), bool include_offsets = true); + native version("4.15.1") Vector3, Vector3 TransformByNamedBone(Name boneName, Vector3 position, Vector3 direction = (0,0,0), bool include_offsets = true); + + version("4.15.1") Vector3 GetBonePosition(int boneIndex, bool include_offsets = true) + { + return TransformByBone(boneIndex, GetBoneBasePosition(boneIndex), include_offsets:include_offsets); + } + + version("4.15.1") Vector3 GetNamedBonePosition(name boneName, bool include_offsets = true) + { + return GetBonePosition(GetBoneIndex(boneName), include_offsets); + } + + //================================================ + // + // Bone Matrix Getters + // + //================================================ + + //outMatrix will be a 16-length array containing the raw matrix data + native version("4.15.1") void GetBoneMatrixRaw(int boneIndex, out Array outMatrix, bool include_offsets = true); + native version("4.15.1") void GetNamedBoneMatrixRaw(Name boneName, out Array outMatrix, bool include_offsets = true); + + native version("4.15.1") void GetObjectToWorldMatrixRaw(out Array outMatrix); //================================================ // @@ -1426,16 +1476,15 @@ class Actor : Thinker native // //================================================ - native version("4.12") void SetAnimation(Name animName, double framerate = -1, int startFrame = -1, int loopFrame = -1, int endFrame = -1, int interpolateTics = -1, int flags = 0); native version("4.12") ui void SetAnimationUI(Name animName, double framerate = -1, int startFrame = -1, int loopFrame = -1, int endFrame = -1, int interpolateTics = -1, int flags = 0); native version("4.12") void SetAnimationFrameRate(double framerate); native version("4.12") ui void SetAnimationFrameRateUI(double framerate); - native version("4.12") void SetModelFlag(int flag); - native version("4.12") void ClearModelFlag(int flag); - native version("4.12") void ResetModelFlags(); + native version("4.12") void SetModelFlag(int flag, int iqmFlags = 0); + native version("4.12") void ClearModelFlag(int flag, int iqmFlags = 0); + native version("4.12") void ResetModelFlags(bool resetModel = true, bool resetIqm = false); action version("4.12") void A_SetAnimation(Name animName, double framerate = -1, int startFrame = -1, int loopFrame = -1, int endFrame = -1, int interpolateTics = -1, int flags = 0) diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index 7f8f03572..e8825cd2f 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -1554,3 +1554,10 @@ enum ESetBoneMode SB_ADD = 1, SB_REPLACE = 2, }; + +enum EIQMFlags +{ + IQM_GET_BONE_INFO = 1 << 2, + IQM_GET_BONE_INFO_RECALC = 1 << 3, // RECALCULATE BONE INFO INSTANTLY WHEN STATE/ANIMATION CHANGES, MIGHT GET EXPENSIVE +}; +