diff --git a/src/common/models/model.h b/src/common/models/model.h index 7b768d21a..c99f76421 100644 --- a/src/common/models/model.h +++ b/src/common/models/model.h @@ -71,7 +71,7 @@ enum ModelRendererType { GLModelRendererType, SWModelRendererType, - PolyModelRendererType, + MeshBuilderRendererType, NumModelRendererTypes }; diff --git a/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp b/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp index 95d6145eb..8d9bd15de 100644 --- a/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp +++ b/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp @@ -59,6 +59,8 @@ void MeshBuilder::Apply() { MeshApplyState state; + state.vertexBuffer = static_cast*>(mVertexBuffer); + state.indexBuffer = static_cast*>(mIndexBuffer); state.applyData.RenderStyle = mRenderStyle; state.applyData.SpecialEffect = mSpecialEffect; state.applyData.TextureEnabled = mTextureEnabled; @@ -81,3 +83,78 @@ std::pair MeshBuilder::AllocVertices(unsigned int co unsigned int offset = mVertices.Reserve(count); return { &mVertices[offset], offset }; } + +///////////////////////////////////////////////////////////////////////////// + +MeshBuilderModelRender::MeshBuilderModelRender(MeshBuilder& renderstate) : renderstate(renderstate) +{ +} + +void MeshBuilderModelRender::BeginDrawModel(FRenderStyle style, int smf_flags, const VSMatrix& objectToWorldMatrix, bool mirrored) +{ + renderstate.EnableTexture(true); + + VSMatrix normalModelMatrix; + normalModelMatrix.computeNormalMatrix(objectToWorldMatrix); + renderstate.SetModelMatrix(objectToWorldMatrix, normalModelMatrix); +} + +void MeshBuilderModelRender::EndDrawModel(FRenderStyle style, int smf_flags) +{ + renderstate.SetBoneIndexBase(-1); + renderstate.SetModelMatrix(VSMatrix::identity(), VSMatrix::identity()); +} + +IModelVertexBuffer* MeshBuilderModelRender::CreateVertexBuffer(bool needindex, bool singleframe) +{ + return new MeshBuilderModelVertexBuffer(); +} + +VSMatrix MeshBuilderModelRender::GetViewToWorldMatrix() +{ + return VSMatrix::identity(); +} + +void MeshBuilderModelRender::BeginDrawHUDModel(FRenderStyle style, const VSMatrix& objectToWorldMatrix, bool mirrored, int smf_flags) +{ +} + +void MeshBuilderModelRender::EndDrawHUDModel(FRenderStyle style, int smf_flags) +{ +} + +void MeshBuilderModelRender::SetInterpolation(double interpolation) +{ + renderstate.SetInterpolationFactor((double)interpolation); +} + +void MeshBuilderModelRender::SetMaterial(FGameTexture* skin, bool clampNoFilter, FTranslationID translation, void* act_v) +{ + renderstate.SetMaterial(skin, UF_Skin, 0, clampNoFilter ? CLAMP_NOFILTER : CLAMP_NONE, translation, -1, nullptr); +} + +void MeshBuilderModelRender::DrawArrays(int start, int count) +{ + renderstate.Draw(DT_Triangles, start, count); +} + +void MeshBuilderModelRender::DrawElements(int numIndices, size_t offset) +{ + renderstate.DrawIndexed(DT_Triangles, int(offset / sizeof(unsigned int)), numIndices); +} + +void MeshBuilderModelRender::SetupFrame(FModel* model, unsigned int frame1, unsigned int frame2, unsigned int size, int boneStartIndex) +{ + auto mdbuff = static_cast(model->GetVertexBuffer(GetType())); + renderstate.SetBoneIndexBase(boneStartIndex); + if (mdbuff) + { + renderstate.SetVertexBuffer(&mdbuff->vbuf, frame1, frame2); + renderstate.SetIndexBuffer(&mdbuff->ibuf); + } +} + +int MeshBuilderModelRender::UploadBones(const TArray& bones) +{ + return renderstate.UploadBones(bones); +} diff --git a/src/common/rendering/hwrenderer/data/hw_meshbuilder.h b/src/common/rendering/hwrenderer/data/hw_meshbuilder.h index 91af5e351..ebc9ce252 100644 --- a/src/common/rendering/hwrenderer/data/hw_meshbuilder.h +++ b/src/common/rendering/hwrenderer/data/hw_meshbuilder.h @@ -3,10 +3,38 @@ #include "hw_renderstate.h" #include "hw_material.h" #include "flatvertices.h" +#include "modelrenderer.h" +#include "buffers.h" #include class Mesh; +template +class MeshBuilderBuffer : public IBuffer +{ +public: + TArray Data; + + void SetData(size_t size, const void* data, BufferUsageType type) override + { + Data.resize(size); + memcpy(Data.data(), data, size); + } + + void SetSubData(size_t offset, size_t size, const void* data) override + { + memcpy(reinterpret_cast(Data.data()) + offset, data, size); + } + + void* Lock(unsigned int size) override + { + Data.Resize(size); + return Data.data(); + } + + void Unlock() override {} +}; + struct MeshApplyData { FRenderStyle RenderStyle; @@ -28,6 +56,8 @@ public: SurfaceUniforms surfaceUniforms; FMaterialState material; VSMatrix textureMatrix; + MeshBuilderBuffer* vertexBuffer = nullptr; + MeshBuilderBuffer* indexBuffer = nullptr; bool operator<(const MeshApplyState& other) const { @@ -40,6 +70,11 @@ public: if (material.mOverrideShader != other.material.mOverrideShader) return material.mOverrideShader < other.material.mOverrideShader; + if (vertexBuffer != other.vertexBuffer) + return vertexBuffer < other.vertexBuffer; + if (indexBuffer != other.indexBuffer) + return indexBuffer < other.indexBuffer; + int result = memcmp(&applyData, &other.applyData, sizeof(MeshApplyData)); if (result != 0) return result < 0; @@ -122,3 +157,56 @@ private: VSMatrix mTextureMatrix = VSMatrix::identity(); DrawLists* mDrawLists = nullptr; }; + +class MeshBuilderModelVertexBuffer : public IModelVertexBuffer +{ +public: + FModelVertex* LockVertexBuffer(unsigned int size) override + { + return static_cast(vbuf.Lock(size)); + } + + void UnlockVertexBuffer() override + { + } + + unsigned int* LockIndexBuffer(unsigned int size) override + { + return static_cast(ibuf.Lock(size)); + } + + void UnlockIndexBuffer() override + { + } + + MeshBuilderBuffer vbuf; + MeshBuilderBuffer ibuf; +}; + +class MeshBuilderModelRender : public FModelRenderer +{ +public: + MeshBuilderModelRender(MeshBuilder& renderstate); + + ModelRendererType GetType() const override { return ModelRendererType::MeshBuilderRendererType; } + + void BeginDrawModel(FRenderStyle style, int smf_flags, const VSMatrix& objectToWorldMatrix, bool mirrored) override; + void EndDrawModel(FRenderStyle style, int smf_flags) override; + + IModelVertexBuffer* CreateVertexBuffer(bool needindex, bool singleframe) override; + + VSMatrix GetViewToWorldMatrix() override; + + void BeginDrawHUDModel(FRenderStyle style, const VSMatrix& objectToWorldMatrix, bool mirrored, int smf_flags) override; + void EndDrawHUDModel(FRenderStyle style, int smf_flags) override; + + void SetInterpolation(double interpolation) override; + void SetMaterial(FGameTexture* skin, bool clampNoFilter, FTranslationID translation, void* act) 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, int boneStartIndex) override; + int UploadBones(const TArray& bones) override; + +private: + MeshBuilder& renderstate; +}; diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index bca86ea0b..4f0876f1a 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -5,7 +5,7 @@ #include "texturemanager.h" #include "playsim/p_lnspec.h" #include "c_dispatch.h" -#include "g_levellocals.h" +#include "models.h" #include "a_dynlight.h" #include "hw_renderstate.h" #include "hw_vertexbuilder.h" @@ -277,6 +277,31 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap) tile.NeedsInitialBake = true; } +#if 0 + // Collect all the models we want to bake into the level mesh + auto it = doomMap.GetThinkerIterator(); + AActor* thing; + while ((thing = it.Next()) != nullptr) + { + bool isPicnumOverride = thing->picnum.isValid(); + int spritenum = thing->sprite; + FSpriteModelFrame* modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing, spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); + if (modelframe && modelframe->modelIDs.size() != 0) + { + DVector3 thingpos = thing->Pos(); + double x = thingpos.X + thing->WorldOffset.X; + double z = thingpos.Z + thing->WorldOffset.Z; + double y = thingpos.Y + thing->WorldOffset.Y; + + MeshBuilder builder; + MeshBuilderModelRender renderer(builder); + RenderModel(&renderer, x, y, z, modelframe, thing, 0.0); + + // To do: add the MeshBuilder output as surfaces + } + } +#endif + CreateCollision(); UploadPortals();