diff --git a/src/common/models/model.h b/src/common/models/model.h index 250f231e7..48e4ed34a 100644 --- a/src/common/models/model.h +++ b/src/common/models/model.h @@ -70,7 +70,7 @@ public: virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) = 0; virtual int FindFrame(const char * name, bool nodefault = false) = 0; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData) = 0; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, 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; } diff --git a/src/common/models/model_iqm.h b/src/common/models/model_iqm.h index ba349cb10..d91157c26 100644 --- a/src/common/models/model_iqm.h +++ b/src/common/models/model_iqm.h @@ -109,7 +109,7 @@ public: 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, int translation, const FTextureID* surfaceskinids, const TArray& boneData) override; + void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; void BuildVertexBuffer(FModelRenderer* renderer) override; void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override; const TArray* AttachAnimationData() override; diff --git a/src/common/models/model_kvx.h b/src/common/models/model_kvx.h index 6cea51380..c801e5c01 100644 --- a/src/common/models/model_kvx.h +++ b/src/common/models/model_kvx.h @@ -59,7 +59,7 @@ public: 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, int translation, const FTextureID* surfaceskinids, const TArray& boneData) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, 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 4b828b78d..9ead5e60b 100644 --- a/src/common/models/model_md2.h +++ b/src/common/models/model_md2.h @@ -113,7 +113,7 @@ public: 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, int translation, const FTextureID* surfaceskinids, const TArray& boneData) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, 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 96425649c..b53cd3ebb 100644 --- a/src/common/models/model_md3.h +++ b/src/common/models/model_md3.h @@ -67,7 +67,7 @@ public: 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, int translation, const FTextureID* surfaceskinids, const TArray& boneData) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, 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 7e15c8735..e70679b0a 100644 --- a/src/common/models/model_obj.h +++ b/src/common/models/model_obj.h @@ -98,7 +98,7 @@ public: ~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, int translation, const FTextureID* surfaceskinids, const TArray& boneData) override; + void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, 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 67efbdbca..5123a22e9 100644 --- a/src/common/models/model_ue1.h +++ b/src/common/models/model_ue1.h @@ -26,7 +26,7 @@ public: 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, int translation, const FTextureID* surfaceskinids, const TArray& boneData) override; + void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, 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 dce0ebf21..18c49f641 100644 --- a/src/common/models/modelrenderer.h +++ b/src/common/models/modelrenderer.h @@ -24,6 +24,6 @@ public: virtual void SetMaterial(FGameTexture *skin, bool clampNoFilter, int translation) = 0; virtual void DrawArrays(int start, int count) = 0; virtual void DrawElements(int numIndices, size_t offset) = 0; - virtual void SetupFrame(FModel* model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) = 0; + virtual int SetupFrame(FModel* model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) { return -1; }; }; diff --git a/src/common/models/models_iqm.cpp b/src/common/models/models_iqm.cpp index 4ecbce928..f684f8eed 100644 --- a/src/common/models/models_iqm.cpp +++ b/src/common/models/models_iqm.cpp @@ -60,7 +60,7 @@ bool IQMModel::Load(const char* path, int lumpnum, const char* buffer, int lengt uint32_t ofs_extensions = reader.ReadUInt32(); if (num_meshes <= 0) - I_FatalError("Invalid model: \"%s%s\", no mesh data is unsupported", path, fileSystem.GetLongName(mLumpNum)); + I_FatalError("Invalid model: \"%s%s\", no mesh data is unsupported", path, fileSystem.GetLongName(mLumpNum).GetChars()); if (num_text == 0) return false; @@ -493,9 +493,9 @@ int IQMModel::FindFrame(const char* name, bool nodefault) return FErr_NotFound; } -void IQMModel::RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame1, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData) +void IQMModel::RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame1, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) { - renderer->SetupFrame(this, 0, 0, NumVertices, boneData, 0); + renderer->SetupFrame(this, 0, 0, NumVertices, boneData, boneStartPosition); FGameTexture* lastSkin = nullptr; for (int i = 0; i < Meshes.Size(); i++) diff --git a/src/common/models/models_md2.cpp b/src/common/models/models_md2.cpp index 001ddc855..4f2a12d4e 100644 --- a/src/common/models/models_md2.cpp +++ b/src/common/models/models_md2.cpp @@ -363,7 +363,7 @@ int FDMDModel::FindFrame(const char* name, bool nodefault) // //=========================================================================== -void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID*, const TArray& boneData) +void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID*, const TArray& boneData, int boneStartPosition) { if (frameno >= info.numFrames || frameno2 >= info.numFrames) return; @@ -376,7 +376,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, {}); + 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 e3090f0a3..512794293 100644 --- a/src/common/models/models_md3.cpp +++ b/src/common/models/models_md3.cpp @@ -343,7 +343,7 @@ int FMD3Model::FindFrame(const char* name, bool nodefault) // //=========================================================================== -void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData) +void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) { if ((unsigned)frameno >= Frames.Size() || (unsigned)frameno2 >= Frames.Size()) return; @@ -373,7 +373,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, {}); + 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 3e94eda09..65ec72915 100644 --- a/src/common/models/models_obj.cpp +++ b/src/common/models/models_obj.cpp @@ -628,7 +628,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, int translation, const FTextureID* surfaceskinids, const TArray& boneData) +void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) { // Prevent the model from rendering if the frame number is < 0 if (frameno < 0 || frameno2 < 0) return; @@ -657,7 +657,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, {}); + 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 d32bd154e..416f9a391 100644 --- a/src/common/models/models_ue1.cpp +++ b/src/common/models/models_ue1.cpp @@ -229,7 +229,7 @@ int FUE1Model::FindFrame(const char* name, bool nodefault) return index; } -void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData) +void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) { // the moment of magic if ( (frame < 0) || (frame2 < 0) || (frame >= numFrames) || (frame2 >= numFrames) ) return; @@ -260,7 +260,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, {}); + 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 6fe27d16e..6af34cf23 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, int translation, const FTextureID*, const TArray& boneData) +void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID*, const TArray& boneData, int boneStartPosition) { renderer->SetMaterial(skin, true, translation); - renderer->SetupFrame(this, 0, 0, 0, {}); + renderer->SetupFrame(this, 0, 0, 0, {}, -1); renderer->DrawElements(mNumIndices, 0); } diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index 49842fbd9..9c6e30a17 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -287,6 +287,8 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr TArray surfaceskinids; TArray boneData = TArray(); + int boneStartingPosition = 0; + bool evaluatedSingle = false; for (int i = 0; i < modelsamount; i++) { @@ -352,22 +354,24 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr const TArray* animationData = nullptr; - bool attachments = smf->flags & MDL_MODELSAREATTACHMENTS; bool nextFrame = smfNext && modelframe != modelframenext; if (animationid >= 0) { FModel* animation = Models[animationid]; animationData = animation->AttachAnimationData(); - if(!attachments || boneData.Size() == 0) - boneData = animation->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, *animationData); - } - else boneData = mdl->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, *animationData); - if (smfNext && modelframe != modelframenext) - mdl->RenderFrame(renderer, tex, modelframe, modelframenext, inter, translation, ssidp, boneData); + if ((!smf->flags & MDL_MODELSAREATTACHMENTS) || evaluatedSingle == false) + { + boneData = animation->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, *animationData); + boneStartingPosition = renderer->SetupFrame(animation, 0, 0, 0, boneData, -1); + evaluatedSingle = true; + } + } else - mdl->RenderFrame(renderer, tex, modelframe, modelframe, 0.f, translation, ssidp, boneData); + boneData = mdl->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, *animationData); + + mdl->RenderFrame(renderer, tex, modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, translation, ssidp, boneData, boneStartingPosition); } } } diff --git a/src/rendering/hwrenderer/hw_models.cpp b/src/rendering/hwrenderer/hw_models.cpp index d8d3156e2..0738276ff 100644 --- a/src/rendering/hwrenderer/hw_models.cpp +++ b/src/rendering/hwrenderer/hw_models.cpp @@ -136,12 +136,13 @@ void FHWModelRenderer::DrawElements(int numIndices, size_t offset) // //=========================================================================== -void FHWModelRenderer::SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) +int FHWModelRenderer::SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) { auto mdbuff = static_cast(model->GetVertexBuffer(GetType())); - boneIndexBase = screen->mBones->UploadBones(bones); - state.SetBoneIndexBase(screen->mBones->UploadBones(bones)); + boneIndexBase = boneStartIndex >= 0 ? boneStartIndex : screen->mBones->UploadBones(bones); + state.SetBoneIndexBase(boneIndexBase); 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 da3cce9cf..32248152b 100644 --- a/src/rendering/hwrenderer/hw_models.h +++ b/src/rendering/hwrenderer/hw_models.h @@ -56,7 +56,7 @@ public: void SetMaterial(FGameTexture *skin, bool clampNoFilter, int translation) override; void DrawArrays(int start, int count) override; void DrawElements(int numIndices, size_t offset) override; - void SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) override; + int SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) override; };