From 3d2f9e06ed39c664ce4e387a74c26706d7f928cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 26 Jan 2025 17:25:27 -0300 Subject: [PATCH 1/5] remove bone component cache to decrease memory consumption caching this is entirely unnecessary, as it changes every frame --- src/common/models/bonecomponents.h | 11 --- src/common/models/model.h | 6 +- src/common/models/model_iqm.h | 12 +-- src/common/models/model_kvx.h | 2 +- src/common/models/model_md2.h | 2 +- src/common/models/model_md3.h | 2 +- src/common/models/model_obj.h | 2 +- src/common/models/model_ue1.h | 2 +- src/common/models/modelrenderer.h | 2 +- src/common/models/models_iqm.cpp | 82 +++++++------------ src/common/models/models_md2.cpp | 4 +- src/common/models/models_md3.cpp | 4 +- src/common/models/models_obj.cpp | 4 +- src/common/models/models_ue1.cpp | 4 +- src/common/models/models_voxel.cpp | 4 +- .../hwrenderer/data/hw_bonebuffer.cpp | 3 + src/playsim/actor.h | 1 - src/playsim/p_actionfunctions.cpp | 2 +- src/playsim/p_mobj.cpp | 1 - src/r_data/models.cpp | 31 ++++--- src/rendering/hwrenderer/hw_models.cpp | 9 +- src/rendering/hwrenderer/hw_models.h | 2 +- 22 files changed, 79 insertions(+), 113 deletions(-) diff --git a/src/common/models/bonecomponents.h b/src/common/models/bonecomponents.h index 313b0832ee..f4f221f3ba 100644 --- a/src/common/models/bonecomponents.h +++ b/src/common/models/bonecomponents.h @@ -6,17 +6,6 @@ #include - -class DBoneComponents : public DObject -{ - DECLARE_CLASS(DBoneComponents, DObject); -public: - TArray> trscomponents; - TArray> trsmatrix; - - DBoneComponents() = default; -}; - struct ModelAnimFrameInterp { float inter = -1.0f; diff --git a/src/common/models/model.h b/src/common/models/model.h index 2be1f54cca..b6d3f48037 100644 --- a/src/common/models/model.h +++ b/src/common/models/model.h @@ -91,15 +91,15 @@ class FModel virtual int FindLastFrame(FName name) { return FErr_NotFound; } virtual double FindFramerate(FName name) { return FErr_NotFound; } - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) = 0; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) = 0; virtual void BuildVertexBuffer(FModelRenderer *renderer) = 0; virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) = 0; virtual float getAspectFactor(float vscale) { return 1.f; } virtual const TArray* AttachAnimationData() { return nullptr; }; - virtual ModelAnimFrame PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData, DBoneComponents* bones, int index) { return nullptr; }; + virtual ModelAnimFrame PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData) { return nullptr; }; - virtual const TArray CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData, DBoneComponents* bones, int index) { return {}; }; + virtual const TArray* CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData) { return nullptr; }; void SetVertexBuffer(int type, IModelVertexBuffer *buffer) { mVBuf[type] = buffer; } IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; } diff --git a/src/common/models/model_iqm.h b/src/common/models/model_iqm.h index c16e8372a6..cf221595f7 100644 --- a/src/common/models/model_iqm.h +++ b/src/common/models/model_iqm.h @@ -116,16 +116,16 @@ class IQMModel : public FModel int FindFirstFrame(FName name) override; int FindLastFrame(FName name) override; double FindFramerate(FName name) override; - void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) override; void BuildVertexBuffer(FModelRenderer* renderer) override; void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override; const TArray* AttachAnimationData() override; - ModelAnimFrame PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData, DBoneComponents* bones, int index) override; - const TArray CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData, DBoneComponents* bones, int index) override; + ModelAnimFrame PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData) override; + const TArray* CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData) override; - ModelAnimFramePrecalculatedIQM 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, DBoneComponents* bones, int index); - const TArray CalculateBonesIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray* animationData, DBoneComponents* bones, int index); + ModelAnimFramePrecalculatedIQM 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); + const TArray* CalculateBonesIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray* animationData); private: void LoadGeometry(); @@ -151,6 +151,8 @@ class IQMModel : public FModel TArray VertexArrays; uint32_t NumVertices = 0; + TArray boneData; // temporary array, used to hold animation data during rendering, set during CalculateBones, uploaded during RenderFrame + TArray Vertices; TArray baseframe; diff --git a/src/common/models/model_kvx.h b/src/common/models/model_kvx.h index 2175bcbca7..e13ec39e9a 100644 --- a/src/common/models/model_kvx.h +++ b/src/common/models/model_kvx.h @@ -59,7 +59,7 @@ class FVoxelModel : public FModel bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; void Initialize(); virtual int FindFrame(const char* name, bool nodefault) override; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) override; virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; FTextureID GetPaletteTexture() const { return mPalette; } void BuildVertexBuffer(FModelRenderer *renderer) override; diff --git a/src/common/models/model_md2.h b/src/common/models/model_md2.h index fd1646dc9b..201cf64069 100644 --- a/src/common/models/model_md2.h +++ b/src/common/models/model_md2.h @@ -113,7 +113,7 @@ class FDMDModel : public FModel virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; virtual int FindFrame(const char* name, bool nodefault) override; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) override; virtual void LoadGeometry(); virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; diff --git a/src/common/models/model_md3.h b/src/common/models/model_md3.h index 045b1cc3b7..fae753b58c 100644 --- a/src/common/models/model_md3.h +++ b/src/common/models/model_md3.h @@ -67,7 +67,7 @@ class FMD3Model : public FModel virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; virtual int FindFrame(const char* name, bool nodefault) override; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) override; void LoadGeometry(); void BuildVertexBuffer(FModelRenderer *renderer); virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; diff --git a/src/common/models/model_obj.h b/src/common/models/model_obj.h index 4fc977c05f..7604934437 100644 --- a/src/common/models/model_obj.h +++ b/src/common/models/model_obj.h @@ -98,7 +98,7 @@ class FOBJModel : public FModel ~FOBJModel(); bool Load(const char* fn, int lumpnum, const char* buffer, int length) override; int FindFrame(const char* name, bool nodefault) override; - void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) override; void BuildVertexBuffer(FModelRenderer* renderer) override; void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override; }; diff --git a/src/common/models/model_ue1.h b/src/common/models/model_ue1.h index 579002f895..447a69ee03 100644 --- a/src/common/models/model_ue1.h +++ b/src/common/models/model_ue1.h @@ -26,7 +26,7 @@ class FUE1Model : public FModel bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; int FindFrame(const char* name, bool nodefault) override; - void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) override; void BuildVertexBuffer(FModelRenderer *renderer) override; void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; void LoadGeometry(); diff --git a/src/common/models/modelrenderer.h b/src/common/models/modelrenderer.h index d2d774eab9..adc93ddedc 100644 --- a/src/common/models/modelrenderer.h +++ b/src/common/models/modelrenderer.h @@ -24,6 +24,6 @@ class FModelRenderer virtual void SetMaterial(FGameTexture *skin, bool clampNoFilter, FTranslationID translation) = 0; virtual void DrawArrays(int start, int count) = 0; virtual void DrawElements(int numIndices, size_t offset) = 0; - virtual int SetupFrame(FModel* model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) { return -1; }; + virtual void SetupFrame(FModel* model, unsigned int frame1, unsigned int frame2, unsigned int size, int boneStartIndex) {}; }; diff --git a/src/common/models/models_iqm.cpp b/src/common/models/models_iqm.cpp index 1384debce2..d5fb6a152c 100644 --- a/src/common/models/models_iqm.cpp +++ b/src/common/models/models_iqm.cpp @@ -7,9 +7,8 @@ #include "engineerrors.h" #include "dobject.h" #include "bonecomponents.h" - -IMPLEMENT_CLASS(DBoneComponents, false, false); - +#include "v_video.h" +#include "hw_bonebuffer.h" IQMModel::IQMModel() { @@ -469,9 +468,10 @@ double IQMModel::FindFramerate(FName name) return FErr_NotFound; } -void IQMModel::RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame1, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) +void IQMModel::RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame1, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) { - renderer->SetupFrame(this, 0, 0, NumVertices, boneData, boneStartPosition); + + renderer->SetupFrame(this, 0, 0, NumVertices, boneStartPosition >= 0 ? boneStartPosition : screen->mBones->UploadBones(boneData)); FGameTexture* lastSkin = nullptr; for (unsigned i = 0; i < Meshes.Size(); i++) @@ -563,51 +563,51 @@ static TRS InterpolateBone(const TRS &from, const TRS &to, float t, float invt) #include "printf.h" -ModelAnimFrame IQMModel::PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData, DBoneComponents* bones, int index) +ModelAnimFrame IQMModel::PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData) { if(inter <= 0) { - return CalculateFrameIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData, bones, index); + return CalculateFrameIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData); } else if(std::holds_alternative(from)) { auto &from_interp = std::get(from); - return CalculateFrameIQM(from_interp.frame2, to.frame2, inter, from_interp.frame1, from_interp.inter, to.frame1, to.inter, nullptr, animationData, bones, index); + return CalculateFrameIQM(from_interp.frame2, to.frame2, inter, from_interp.frame1, from_interp.inter, to.frame1, to.inter, nullptr, animationData); } else if(std::holds_alternative(from)) { - return CalculateFrameIQM(0, to.frame2, inter, 0, -1.f, to.frame1, to.inter, &std::get(from), animationData, bones, index); + return CalculateFrameIQM(0, to.frame2, inter, 0, -1.f, to.frame1, to.inter, &std::get(from), animationData); } else { - return CalculateFrameIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData, bones, index); + return CalculateFrameIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData); } } -const TArray IQMModel::CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData, DBoneComponents* bones, int index) +const TArray* IQMModel::CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData) { if(inter <= 0) { - return CalculateBonesIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData, bones, index); + return CalculateBonesIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData); } else if(std::holds_alternative(from)) { auto &from_interp = std::get(from); - return CalculateBonesIQM(from_interp.frame2, to.frame2, inter, from_interp.frame1, from_interp.inter, to.frame1, to.inter, nullptr, animationData, bones, index); + return CalculateBonesIQM(from_interp.frame2, to.frame2, inter, from_interp.frame1, from_interp.inter, to.frame1, to.inter, nullptr, animationData); } else if(std::holds_alternative(from)) { - return CalculateBonesIQM(0, to.frame2, inter, 0, -1.f, to.frame1, to.inter, &std::get(from), animationData, bones, index); + return CalculateBonesIQM(0, to.frame2, inter, 0, -1.f, to.frame1, to.inter, &std::get(from), animationData); } else { - return CalculateBonesIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData, bones, index); + return CalculateBonesIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData); } } -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, DBoneComponents* boneComponentData, int index) +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) { ModelAnimFramePrecalculatedIQM out; const TArray& animationFrames = animationData ? *animationData : TRSData; @@ -661,18 +661,13 @@ ModelAnimFramePrecalculatedIQM IQMModel::CalculateFrameIQM(int frame1, int frame return out; } -const TArray IQMModel::CalculateBonesIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray* animationData, DBoneComponents* boneComponentData, int index) +const TArray* IQMModel::CalculateBonesIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray* animationData) { const TArray& animationFrames = animationData ? *animationData : TRSData; if (Joints.Size() > 0) { int numbones = Joints.SSize(); - if (boneComponentData->trscomponents[index].SSize() != numbones) - boneComponentData->trscomponents[index].Resize(numbones); - if (boneComponentData->trsmatrix[index].SSize() != numbones) - boneComponentData->trsmatrix[index].Resize(numbones); - frame1 = clamp(frame1, 0, (animationFrames.SSize() - 1) / numbones); frame2 = clamp(frame2, 0, (animationFrames.SSize() - 1) / numbones); @@ -686,14 +681,16 @@ const TArray IQMModel::CalculateBonesIQM(int frame1, int frame2, float float invt1 = 1.0f - inter1_prev; float invt2 = 1.0f - inter2_prev; - float swapYZ[16] = { 0.0f }; - swapYZ[0 + 0 * 4] = 1.0f; - swapYZ[1 + 2 * 4] = 1.0f; - swapYZ[2 + 1 * 4] = 1.0f; - swapYZ[3 + 3 * 4] = 1.0f; + constexpr const float swapYZ[16] + { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + boneData.Resize(numbones); - TArray bones(numbones, true); - TArray modifiedBone(numbones, true); for (int i = 0; i < numbones; i++) { TRS prev; @@ -724,33 +721,16 @@ const TArray IQMModel::CalculateBonesIQM(int frame1, int frame2, float bone = inter < 0 ? animationFrames[offset1 + i] : InterpolateBone(prev, next , inter, invt); } - if (Joints[i].Parent >= 0 && modifiedBone[Joints[i].Parent]) - { - boneComponentData->trscomponents[index][i] = bone; - modifiedBone[i] = true; - } - else if (boneComponentData->trscomponents[index][i].Equals(bone)) - { - bones[i] = boneComponentData->trsmatrix[index][i]; - modifiedBone[i] = false; - continue; - } - else - { - boneComponentData->trscomponents[index][i] = bone; - modifiedBone[i] = true; - } - VSMatrix m; m.loadIdentity(); m.translate(bone.translation.X, bone.translation.Y, bone.translation.Z); m.multQuaternion(bone.rotation); m.scale(bone.scaling.X, bone.scaling.Y, bone.scaling.Z); - VSMatrix& result = bones[i]; + VSMatrix& result = boneData[i]; if (Joints[i].Parent >= 0) { - result = bones[Joints[i].Parent]; + result = boneData[Joints[i].Parent]; result.multMatrix(swapYZ); result.multMatrix(baseframe[Joints[i].Parent]); result.multMatrix(m); @@ -765,9 +745,7 @@ const TArray IQMModel::CalculateBonesIQM(int frame1, int frame2, float result.multMatrix(swapYZ); } - boneComponentData->trsmatrix[index] = bones; - - return bones; + return &boneData; } - return {}; + return nullptr; } diff --git a/src/common/models/models_md2.cpp b/src/common/models/models_md2.cpp index 280c4d265f..d7fa476624 100644 --- a/src/common/models/models_md2.cpp +++ b/src/common/models/models_md2.cpp @@ -364,7 +364,7 @@ int FDMDModel::FindFrame(const char* name, bool nodefault) // //=========================================================================== -void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID*, const TArray& boneData, int boneStartPosition) +void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID*, int boneStartPosition) { if (frameno >= info.numFrames || frameno2 >= info.numFrames) return; @@ -377,7 +377,7 @@ void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f renderer->SetInterpolation(inter); renderer->SetMaterial(skin, false, translation); - renderer->SetupFrame(this, frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3, {}, -1); + renderer->SetupFrame(this, frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3, -1); renderer->DrawArrays(0, lodInfo[0].numTriangles * 3); renderer->SetInterpolation(0.f); } diff --git a/src/common/models/models_md3.cpp b/src/common/models/models_md3.cpp index 327cbff88a..23e8119284 100644 --- a/src/common/models/models_md3.cpp +++ b/src/common/models/models_md3.cpp @@ -345,7 +345,7 @@ int FMD3Model::FindFrame(const char* name, bool nodefault) // //=========================================================================== -void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) +void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) { if ((unsigned)frameno >= Frames.Size() || (unsigned)frameno2 >= Frames.Size()) return; @@ -375,7 +375,7 @@ void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f } renderer->SetMaterial(surfaceSkin, false, translation); - renderer->SetupFrame(this, surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices, {}, -1); + renderer->SetupFrame(this, surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices, -1); renderer->DrawElements(surf->numTriangles * 3, surf->iindex * sizeof(unsigned int)); } renderer->SetInterpolation(0.f); diff --git a/src/common/models/models_obj.cpp b/src/common/models/models_obj.cpp index 43e89b1d21..0d9b6c9513 100644 --- a/src/common/models/models_obj.cpp +++ b/src/common/models/models_obj.cpp @@ -630,7 +630,7 @@ int FOBJModel::FindFrame(const char* name, bool nodefault) * @param inter The amount to interpolate the two frames. * @param translation The translation for the skin */ -void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) +void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) { // Prevent the model from rendering if the frame number is < 0 if (frameno < 0 || frameno2 < 0) return; @@ -659,7 +659,7 @@ void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f } renderer->SetMaterial(userSkin, false, translation); - renderer->SetupFrame(this, surf->vbStart, surf->vbStart, surf->numTris * 3, {}, -1); + renderer->SetupFrame(this, surf->vbStart, surf->vbStart, surf->numTris * 3, -1); renderer->DrawArrays(0, surf->numTris * 3); } } diff --git a/src/common/models/models_ue1.cpp b/src/common/models/models_ue1.cpp index 8106592617..155e6d13ff 100644 --- a/src/common/models/models_ue1.cpp +++ b/src/common/models/models_ue1.cpp @@ -232,7 +232,7 @@ int FUE1Model::FindFrame(const char* name, bool nodefault) return index; } -void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) +void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) { // the moment of magic if ( (frame < 0) || (frame2 < 0) || (frame >= numFrames) || (frame2 >= numFrames) ) return; @@ -263,7 +263,7 @@ void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int f // TODO: Handle per-group render styles and other flags once functions for it are implemented // Future note: poly renderstyles should always be enforced unless the actor itself has a style other than Normal renderer->SetMaterial(sskin,false,translation); - renderer->SetupFrame(this, vofs + frame * fsize, vofs + frame2 * fsize, vsize, {}, -1); + renderer->SetupFrame(this, vofs + frame * fsize, vofs + frame2 * fsize, vsize, -1); renderer->DrawArrays(0,vsize); vofs += vsize; } diff --git a/src/common/models/models_voxel.cpp b/src/common/models/models_voxel.cpp index e6cd5f8373..9b66571830 100644 --- a/src/common/models/models_voxel.cpp +++ b/src/common/models/models_voxel.cpp @@ -400,9 +400,9 @@ float FVoxelModel::getAspectFactor(float stretch) // //=========================================================================== -void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID*, const TArray& boneData, int boneStartPosition) +void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID*, int boneStartPosition) { renderer->SetMaterial(skin, true, translation); - renderer->SetupFrame(this, 0, 0, 0, {}, -1); + renderer->SetupFrame(this, 0, 0, 0, -1); renderer->DrawElements(mNumIndices, 0); } diff --git a/src/common/rendering/hwrenderer/data/hw_bonebuffer.cpp b/src/common/rendering/hwrenderer/data/hw_bonebuffer.cpp index e6de054114..72bd712600 100644 --- a/src/common/rendering/hwrenderer/data/hw_bonebuffer.cpp +++ b/src/common/rendering/hwrenderer/data/hw_bonebuffer.cpp @@ -74,6 +74,7 @@ void BoneBuffer::Clear() int BoneBuffer::UploadBones(const TArray& bones) { + Map(); int totalsize = bones.Size(); if (totalsize > (int)mMaxUploadSize) { @@ -90,10 +91,12 @@ int BoneBuffer::UploadBones(const TArray& bones) if (thisindex + totalsize <= mBufferSize) { memcpy(mBufferPointer + thisindex * BONE_SIZE, bones.Data(), totalsize * BONE_SIZE); + Unmap(); return thisindex; } else { + Unmap(); return -1; // Buffer is full. Since it is being used live at the point of the upload we cannot do much here but to abort. } } diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 5185172622..14f04e9ee4 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -1155,7 +1155,6 @@ class AActor final : public DThinker double Speed; double FloatSpeed; TObjPtr modelData; - TObjPtr boneComponentData; // interaction info FBlockNode *BlockNode; // links in blocks (if needed) diff --git a/src/playsim/p_actionfunctions.cpp b/src/playsim/p_actionfunctions.cpp index 8d50993d90..1f18209bbc 100644 --- a/src/playsim/p_actionfunctions.cpp +++ b/src/playsim/p_actionfunctions.cpp @@ -5209,7 +5209,7 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s animationData = animation->AttachAnimationData(); } - self->modelData->prevAnim = animation->PrecalculateFrame(self->modelData->prevAnim, to, inter, animationData, self->boneComponentData, 0); + self->modelData->prevAnim = animation->PrecalculateFrame(self->modelData->prevAnim, to, inter, animationData); } else { diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 5c31523250..61d54c2ece 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -178,7 +178,6 @@ IMPLEMENT_POINTERS_START(AActor) IMPLEMENT_POINTER(alternative) IMPLEMENT_POINTER(ViewPos) IMPLEMENT_POINTER(modelData) - IMPLEMENT_POINTER(boneComponentData) IMPLEMENT_POINTERS_END //========================================================================== diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index a13d569986..79ed05d8c6 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -45,6 +45,8 @@ #include "modelrenderer.h" #include "actor.h" #include "actorinlines.h" +#include "v_video.h" +#include "hw_bonebuffer.h" #ifdef _MSC_VER @@ -394,8 +396,8 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr TArray surfaceskinids; - TArray boneData; - int boneStartingPosition = 0; + const TArray *boneData; + int boneStartingPosition = -1; bool evaluatedSingle = false; for (unsigned i = 0; i < modelsamount; i++) @@ -520,15 +522,6 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr bool nextFrame = smfNext && modelframe != modelframenext; - if (actor->boneComponentData == nullptr) - { - auto ptr = Create(); - ptr->trscomponents.Resize(modelsamount); - ptr->trsmatrix.Resize(modelsamount); - actor->boneComponentData = ptr; - GC::WriteBarrier(actor, ptr); - } - // [RL0] while per-model animations aren't done, DECOUPLEDANIMATIONS does the same as MODELSAREATTACHMENTS if(!evaluatedSingle) { @@ -545,18 +538,24 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr { if(decoupled_frame.frame1 != -1) { - boneData = animation->CalculateBones(actor->modelData->prevAnim, decoupled_frame, inter, animationData, actor->boneComponentData, i); + boneData = animation->CalculateBones(actor->modelData->prevAnim, decoupled_frame, inter, animationData); } } else { - boneData = animation->CalculateBones(nullptr, {nextFrame ? inter : -1.0f, modelframe, modelframenext}, -1.0f, animationData, actor->boneComponentData, i); + boneData = animation->CalculateBones(nullptr, {nextFrame ? inter : -1.0f, modelframe, modelframenext}, -1.0f, animationData); } - boneStartingPosition = renderer->SetupFrame(animation, 0, 0, 0, boneData, -1); - evaluatedSingle = (smf_flags & MDL_MODELSAREATTACHMENTS) || is_decoupled; + + if(smf_flags & MDL_MODELSAREATTACHMENTS || is_decoupled) + { + boneStartingPosition = boneData ? screen->mBones->UploadBones(*boneData) : -1; + evaluatedSingle = true; + } + + boneData = nullptr; } - mdl->RenderFrame(renderer, tex, modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : -1.f, translation, ssidp, boneData, boneStartingPosition); + mdl->RenderFrame(renderer, tex, modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : -1.f, translation, ssidp, boneStartingPosition); } } } diff --git a/src/rendering/hwrenderer/hw_models.cpp b/src/rendering/hwrenderer/hw_models.cpp index 06ce5942e9..82b0d764e8 100644 --- a/src/rendering/hwrenderer/hw_models.cpp +++ b/src/rendering/hwrenderer/hw_models.cpp @@ -138,18 +138,15 @@ void FHWModelRenderer::DrawElements(int numIndices, size_t offset) // //=========================================================================== -int FHWModelRenderer::SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) +void FHWModelRenderer::SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size, int boneStartIndex) { auto mdbuff = static_cast(model->GetVertexBuffer(GetType())); - screen->mBones->Map(); - boneIndexBase = boneStartIndex >= 0 ? boneStartIndex : screen->mBones->UploadBones(bones); - screen->mBones->Unmap(); - state.SetBoneIndexBase(boneIndexBase); + //boneIndexBase = boneStartIndex;//boneStartIndex >= 0 ? boneStartIndex : screen->mBones->UploadBones(bones); + state.SetBoneIndexBase(boneStartIndex); if (mdbuff) { state.SetVertexBuffer(mdbuff->vertexBuffer(), frame1, frame2); if (mdbuff->indexBuffer()) state.SetIndexBuffer(mdbuff->indexBuffer()); } - return boneIndexBase; } diff --git a/src/rendering/hwrenderer/hw_models.h b/src/rendering/hwrenderer/hw_models.h index c3e5125da6..2f5470e570 100644 --- a/src/rendering/hwrenderer/hw_models.h +++ b/src/rendering/hwrenderer/hw_models.h @@ -56,7 +56,7 @@ class FHWModelRenderer : public FModelRenderer void SetMaterial(FGameTexture *skin, bool clampNoFilter, FTranslationID translation) override; void DrawArrays(int start, int count) override; void DrawElements(int numIndices, size_t offset) override; - int SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) override; + void SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size, int boneStartIndex) override; }; From e0394ef16a56cbc21996680bc2b4c65ea7158283 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 24 Jan 2025 14:07:33 -0500 Subject: [PATCH 2/5] Added flags for angle handling on bounce Allows for keeping the current angle on bounce or modifying the pitch. --- src/playsim/actor.h | 2 ++ src/playsim/p_map.cpp | 12 +++++++++--- src/playsim/p_mobj.cpp | 9 +++++++-- src/scripting/thingdef_data.cpp | 2 ++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 14f04e9ee4..edd04cee5f 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -548,6 +548,8 @@ enum ActorBounceFlag BOUNCE_BounceOnUnrips = 1<<16, // projectile bounces on actors with DONTRIP BOUNCE_NotOnSky = 1<<17, // Don't bounce on sky floors / ceilings / walls BOUNCE_DEH = 1<<18, // Flag was set through Dehacked. + BOUNCE_KeepAngle = 1<<19, // Don't change yaw when bouncing off a surface. + BOUNCE_ModifyPitch = 1<<20, // Change pitch when bouncing off a surface. BOUNCE_TypeMask = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff | BOUNCE_HereticType | BOUNCE_MBF, diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index aaa45e4dc6..04ffa12c06 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -3653,7 +3653,8 @@ bool FSlide::BounceWall(AActor *mo) } moveangle = mo->Vel.Angle(); deltaangle = (lineangle * 2) - moveangle; - mo->Angles.Yaw = deltaangle; + if (!(mo->BounceFlags & BOUNCE_KeepAngle)) + mo->Angles.Yaw = deltaangle; movelen = mo->Vel.XY().Length() * GetWallBounceFactor(mo); @@ -3751,8 +3752,10 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop) DAngle angle = BlockingMobj->AngleTo(mo) + DAngle::fromDeg((pr_bounce() % 16) - 8); double speed = mo->VelXYToSpeed() * GetWallBounceFactor(mo); // [GZ] was 0.75, using wallbouncefactor seems more consistent if (fabs(speed) < EQUAL_EPSILON) speed = 0; - mo->Angles.Yaw = angle; - mo->VelFromAngle(speed); + if (!(mo->BounceFlags & BOUNCE_KeepAngle)) + mo->Angles.Yaw = angle; + mo->Vel.X = speed * angle.Cos(); + mo->Vel.Y = speed * angle.Sin(); mo->PlayBounceSound(true, 1.0); } else @@ -3781,6 +3784,9 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop) mo->Vel *= mo->bouncefactor; } + if (mo->BounceFlags & BOUNCE_ModifyPitch) + mo->Angles.Pitch = -VecToAngle(mo->Vel.XY().Length(), mo->Vel.Z); + mo->PlayBounceSound(true, 1.0); if (mo->BounceFlags & BOUNCE_MBF) // Bring it to rest below a certain speed { diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 61d54c2ece..9bc1854719 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -1824,7 +1824,8 @@ bool AActor::FloorBounceMissile (secplane_t &plane, bool is3DFloor) if (BounceFlags & (BOUNCE_HereticType | BOUNCE_MBF)) { Vel -= norm * dot; - AngleFromVel(); + if (!(BounceFlags & BOUNCE_KeepAngle)) + AngleFromVel(); if (!(BounceFlags & BOUNCE_MBF)) // Heretic projectiles die, MBF projectiles don't. { flags |= MF_INBOUNCE; @@ -1838,9 +1839,13 @@ bool AActor::FloorBounceMissile (secplane_t &plane, bool is3DFloor) { // The reflected velocity keeps only about 70% of its original speed Vel = (Vel - norm * dot) * bouncefactor; - AngleFromVel(); + if (!(BounceFlags & BOUNCE_KeepAngle)) + AngleFromVel(); } + if (BounceFlags & BOUNCE_ModifyPitch) + Angles.Pitch = -VecToAngle(Vel.XY().Length(), Vel.Z); + PlayBounceSound(true, 1.0); // Set bounce state diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index fa8d666748..8692936c11 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -407,6 +407,8 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG2(BOUNCE_NotOnShootables, DONTBOUNCEONSHOOTABLES, AActor, BounceFlags), DEFINE_FLAG2(BOUNCE_BounceOnUnrips, BOUNCEONUNRIPPABLES, AActor, BounceFlags), DEFINE_FLAG2(BOUNCE_NotOnSky, DONTBOUNCEONSKY, AActor, BounceFlags), + DEFINE_FLAG2(BOUNCE_KeepAngle, KEEPBOUNCEANGLE, AActor, BounceFlags), + DEFINE_FLAG2(BOUNCE_ModifyPitch, BOUNCEMODIFIESPITCH, AActor, BounceFlags), DEFINE_FLAG2(OF_Transient, NOSAVEGAME, AActor, ObjectFlags), From 162ab3c4ec9bc906a626ad2b10bcb5d3ffc2aa89 Mon Sep 17 00:00:00 2001 From: Adam Kaminski Date: Fri, 24 Jan 2025 10:33:56 -0500 Subject: [PATCH 3/5] Fixed ACS scripts executing a function from another library that cause a division/modulus of zero from aborting the game. --- src/playsim/p_acs.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index 89aee643d2..652dd61412 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -10337,6 +10337,11 @@ int DLevelScript::RunScript() } } + // There are several or more p-codes that can trigger a division or modulus of zero. + // Reset the active behavior back to the original if this happens. + if (state == SCRIPT_DivideBy0 || state == SCRIPT_ModulusBy0) + activeBehavior = savedActiveBehavior; + if (runaway != 0 && InModuleScriptNumber >= 0) { auto scriptptr = activeBehavior->GetScriptPtr(InModuleScriptNumber); From aae8c12cdf5ed515aaacf9084a6d16282190e084 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Tue, 28 Jan 2025 08:49:41 +0800 Subject: [PATCH 4/5] Add a particle flag to allow user shaders on the sprites --- src/playsim/p_effect.h | 1 + src/rendering/hwrenderer/scene/hw_sprites.cpp | 2 +- wadsrc/static/zscript/constants.zs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 1e5ba27053..29042b293d 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -70,6 +70,7 @@ enum EParticleFlags SPF_NOFACECAMERA = 1 << 12, SPF_ROLLCENTER = 1 << 13, SPF_STRETCHPIXELS = 1 << 14, + SPF_ALLOWSHADERS = 1 << 15, }; class DVisualThinker; diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index b7e1f20fe1..f3ab6d4c32 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -1416,7 +1416,7 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s foglevel = (uint8_t)clamp(sector->lightlevel, 0, 255); trans = particle->alpha; - OverrideShader = 0; + OverrideShader = (particle->flags & SPF_ALLOWSHADERS) ? -1 : 0; modelframe = nullptr; texture = nullptr; topclip = LARGE_VALUE; diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index 5421c188e0..cbc14f9ef4 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -723,6 +723,7 @@ enum EParticleFlags SPF_NOFACECAMERA = 1 << 12, SPF_ROLLCENTER = 1 << 13, SPF_STRETCHPIXELS = 1 << 14, + SPF_ALLOWSHADERS = 1 << 15, SPF_RELATIVE = SPF_RELPOS|SPF_RELVEL|SPF_RELACCEL|SPF_RELANG }; From 3adddd6674c26b14e861b28440d7749b024c2876 Mon Sep 17 00:00:00 2001 From: Jon Daniel Date: Wed, 29 Jan 2025 21:14:09 +0100 Subject: [PATCH 5/5] fix compile error missing tarray.h --- src/common/engine/m_random.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/engine/m_random.h b/src/common/engine/m_random.h index ba0bcaf626..bc7eb4d0da 100644 --- a/src/common/engine/m_random.h +++ b/src/common/engine/m_random.h @@ -37,6 +37,7 @@ #include #include "basics.h" +#include "tarray.h" #include "sfmt/SFMTObj.h" class FSerializer;