Model rendering to mesh builder

This commit is contained in:
Magnus Norddahl 2025-06-10 20:32:27 +02:00
commit cfe282f4bd
4 changed files with 192 additions and 2 deletions

View file

@ -71,7 +71,7 @@ enum ModelRendererType
{
GLModelRendererType,
SWModelRendererType,
PolyModelRendererType,
MeshBuilderRendererType,
NumModelRendererTypes
};

View file

@ -59,6 +59,8 @@ void MeshBuilder::Apply()
{
MeshApplyState state;
state.vertexBuffer = static_cast<MeshBuilderBuffer<FModelVertex>*>(mVertexBuffer);
state.indexBuffer = static_cast<MeshBuilderBuffer<unsigned int>*>(mIndexBuffer);
state.applyData.RenderStyle = mRenderStyle;
state.applyData.SpecialEffect = mSpecialEffect;
state.applyData.TextureEnabled = mTextureEnabled;
@ -81,3 +83,78 @@ std::pair<FFlatVertex*, unsigned int> 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<MeshBuilderModelVertexBuffer*>(model->GetVertexBuffer(GetType()));
renderstate.SetBoneIndexBase(boneStartIndex);
if (mdbuff)
{
renderstate.SetVertexBuffer(&mdbuff->vbuf, frame1, frame2);
renderstate.SetIndexBuffer(&mdbuff->ibuf);
}
}
int MeshBuilderModelRender::UploadBones(const TArray<VSMatrix>& bones)
{
return renderstate.UploadBones(bones);
}

View file

@ -3,10 +3,38 @@
#include "hw_renderstate.h"
#include "hw_material.h"
#include "flatvertices.h"
#include "modelrenderer.h"
#include "buffers.h"
#include <map>
class Mesh;
template<typename T>
class MeshBuilderBuffer : public IBuffer
{
public:
TArray<T> 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<uint8_t*>(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<FModelVertex>* vertexBuffer = nullptr;
MeshBuilderBuffer<unsigned int>* 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<FModelVertex*>(vbuf.Lock(size));
}
void UnlockVertexBuffer() override
{
}
unsigned int* LockIndexBuffer(unsigned int size) override
{
return static_cast<unsigned int*>(ibuf.Lock(size));
}
void UnlockIndexBuffer() override
{
}
MeshBuilderBuffer<FModelVertex> vbuf;
MeshBuilderBuffer<unsigned int> 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<VSMatrix>& bones) override;
private:
MeshBuilder& renderstate;
};

View file

@ -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>();
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();