From 00d7dd0c64c340e7b03c1908b8ba35bfa80c2e24 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 24 Nov 2017 00:39:10 +0100 Subject: [PATCH] - Implement model rendering in softpoly --- src/CMakeLists.txt | 1 + src/polyrenderer/drawers/poly_draw_args.cpp | 10 + src/polyrenderer/drawers/poly_draw_args.h | 3 + src/polyrenderer/drawers/poly_triangle.cpp | 63 ++++- src/polyrenderer/drawers/poly_triangle.h | 1 + src/polyrenderer/poly_all.cpp | 1 + src/polyrenderer/poly_renderer.cpp | 4 +- src/polyrenderer/poly_renderer.h | 4 +- src/polyrenderer/scene/poly_model.cpp | 255 +++++++++++++++++++ src/polyrenderer/scene/poly_model.h | 82 ++++++ src/polyrenderer/scene/poly_playersprite.cpp | 11 + src/polyrenderer/scene/poly_playersprite.h | 1 + src/polyrenderer/scene/poly_sprite.cpp | 12 + 13 files changed, 444 insertions(+), 4 deletions(-) create mode 100644 src/polyrenderer/scene/poly_model.cpp create mode 100644 src/polyrenderer/scene/poly_model.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 30981fbf00..6c266eb865 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -756,6 +756,7 @@ set( POLYRENDER_SOURCES polyrenderer/scene/poly_wall.cpp polyrenderer/scene/poly_wallsprite.cpp polyrenderer/scene/poly_sprite.cpp + polyrenderer/scene/poly_model.cpp polyrenderer/scene/poly_sky.cpp polyrenderer/scene/poly_light.cpp polyrenderer/drawers/poly_buffer.cpp diff --git a/src/polyrenderer/drawers/poly_draw_args.cpp b/src/polyrenderer/drawers/poly_draw_args.cpp index 0df28f9aa4..5fb7f0288d 100644 --- a/src/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/polyrenderer/drawers/poly_draw_args.cpp @@ -130,6 +130,16 @@ void PolyDrawArgs::DrawArray(PolyRenderThread *thread, const TriVertex *vertices { mVertices = vertices; mVertexCount = vcount; + mElements = nullptr; + mDrawMode = mode; + thread->DrawQueue->Push(*this, PolyTriangleDrawer::is_mirror()); +} + +void PolyDrawArgs::DrawElements(PolyRenderThread *thread, const TriVertex *vertices, const unsigned int *elements, int count, PolyDrawMode mode) +{ + mVertices = vertices; + mElements = elements; + mVertexCount = count; mDrawMode = mode; thread->DrawQueue->Push(*this, PolyTriangleDrawer::is_mirror()); } diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index 34ef56eb25..31780d77ae 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -83,12 +83,14 @@ public: void SetLights(PolyLight *lights, int numLights) { mLights = lights; mNumLights = numLights; } void SetDynLightColor(uint32_t color) { mDynLightColor = color; } void DrawArray(PolyRenderThread *thread, const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); + void DrawElements(PolyRenderThread *thread, const TriVertex *vertices, const unsigned int *elements, int count, PolyDrawMode mode = PolyDrawMode::Triangles); const TriMatrix *ObjectToClip() const { return mObjectToClip; } const PolyClipPlane &ClipPlane(int index) const { return mClipPlane[index]; } const TriVertex *Vertices() const { return mVertices; } int VertexCount() const { return mVertexCount; } + const unsigned int *Elements() const { return mElements; } PolyDrawMode DrawMode() const { return mDrawMode; } bool FaceCullCCW() const { return mFaceCullCCW; } @@ -139,6 +141,7 @@ private: const TriMatrix *mObjectToClip = nullptr; const TriVertex *mVertices = nullptr; int mVertexCount = 0; + const unsigned int *mElements = nullptr; PolyDrawMode mDrawMode = PolyDrawMode::Triangles; bool mFaceCullCCW = false; bool mDepthTest = false; diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index beb2834987..386c4c6304 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -84,6 +84,64 @@ bool PolyTriangleDrawer::is_mirror() return mirror; } +void PolyTriangleDrawer::draw_elements(const PolyDrawArgs &drawargs, WorkerThreadData *thread) +{ + if (drawargs.VertexCount() < 3) + return; + + TriDrawTriangleArgs args; + args.dest = dest; + args.pitch = dest_pitch; + args.clipright = dest_width; + args.clipbottom = dest_height; + args.uniforms = &drawargs; + args.destBgra = dest_bgra; + args.stencilPitch = PolyStencilBuffer::Instance()->BlockWidth(); + args.stencilValues = PolyStencilBuffer::Instance()->Values(); + args.stencilMasks = PolyStencilBuffer::Instance()->Masks(); + args.zbuffer = PolyZBuffer::Instance()->Values(); + + bool ccw = drawargs.FaceCullCCW(); + const TriVertex *vinput = drawargs.Vertices(); + const unsigned int *elements = drawargs.Elements(); + int vcount = drawargs.VertexCount(); + + ShadedTriVertex vert[3]; + if (drawargs.DrawMode() == PolyDrawMode::Triangles) + { + for (int i = 0; i < vcount / 3; i++) + { + for (int j = 0; j < 3; j++) + vert[j] = shade_vertex(drawargs, vinput[*(elements++)]); + draw_shaded_triangle(vert, ccw, &args, thread); + } + } + else if (drawargs.DrawMode() == PolyDrawMode::TriangleFan) + { + vert[0] = shade_vertex(drawargs, vinput[*(elements++)]); + vert[1] = shade_vertex(drawargs, vinput[*(elements++)]); + for (int i = 2; i < vcount; i++) + { + vert[2] = shade_vertex(drawargs, vinput[*(elements++)]); + draw_shaded_triangle(vert, ccw, &args, thread); + vert[1] = vert[2]; + } + } + else // TriangleDrawMode::TriangleStrip + { + vert[0] = shade_vertex(drawargs, vinput[*(elements++)]); + vert[1] = shade_vertex(drawargs, vinput[*(elements++)]); + for (int i = 2; i < vcount; i++) + { + vert[2] = shade_vertex(drawargs, vinput[*(elements++)]); + draw_shaded_triangle(vert, ccw, &args, thread); + vert[0] = vert[1]; + vert[1] = vert[2]; + ccw = !ccw; + } + } +} + void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, WorkerThreadData *thread) { if (drawargs.VertexCount() < 3) @@ -472,7 +530,10 @@ void DrawPolyTrianglesCommand::Execute(DrawerThread *thread) thread_data.core = thread->core; thread_data.num_cores = thread->num_cores; - PolyTriangleDrawer::draw_arrays(args, &thread_data); + if (!args.Elements()) + PolyTriangleDrawer::draw_arrays(args, &thread_data); + else + PolyTriangleDrawer::draw_elements(args, &thread_data); } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/polyrenderer/drawers/poly_triangle.h b/src/polyrenderer/drawers/poly_triangle.h index 4992f6972c..eea3b8531f 100644 --- a/src/polyrenderer/drawers/poly_triangle.h +++ b/src/polyrenderer/drawers/poly_triangle.h @@ -40,6 +40,7 @@ public: private: static ShadedTriVertex shade_vertex(const PolyDrawArgs &drawargs, const TriVertex &v); + static void draw_elements(const PolyDrawArgs &args, WorkerThreadData *thread); static void draw_arrays(const PolyDrawArgs &args, WorkerThreadData *thread); static void draw_shaded_triangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread); static bool is_degenerate(const ShadedTriVertex *vertices); diff --git a/src/polyrenderer/poly_all.cpp b/src/polyrenderer/poly_all.cpp index 62d63c2d3d..216dd88e17 100644 --- a/src/polyrenderer/poly_all.cpp +++ b/src/polyrenderer/poly_all.cpp @@ -14,6 +14,7 @@ #include "scene/poly_scene.cpp" #include "scene/poly_sky.cpp" #include "scene/poly_sprite.cpp" +#include "scene/poly_model.cpp" #include "scene/poly_wall.cpp" #include "scene/poly_wallsprite.cpp" #include "scene/poly_light.cpp" diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index a0aa12c32e..1b00412d1d 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -208,12 +208,12 @@ void PolyRenderer::SetupPerspectiveMatrix() float fovratio = (Viewwindow.WidescreenRatio >= 1.3f) ? 1.333333f : ratio; float fovy = (float)(2 * DAngle::ToDegrees(atan(tan(Viewpoint.FieldOfView.Radians() / 2) / fovratio)).Degrees); - TriMatrix worldToView = + WorldToView = TriMatrix::rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) * TriMatrix::rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) * TriMatrix::scale(1.0f, level.info->pixelstretch, 1.0f) * TriMatrix::swapYZ() * TriMatrix::translate((float)-Viewpoint.Pos.X, (float)-Viewpoint.Pos.Y, (float)-Viewpoint.Pos.Z); - WorldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView; + WorldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * WorldToView; } diff --git a/src/polyrenderer/poly_renderer.h b/src/polyrenderer/poly_renderer.h index 8e5011782a..2ef60a0ea0 100644 --- a/src/polyrenderer/poly_renderer.h +++ b/src/polyrenderer/poly_renderer.h @@ -61,13 +61,15 @@ public: FRenderViewpoint Viewpoint; PolyLightVisibility Light; + TriMatrix WorldToView; + TriMatrix WorldToClip; + private: void RenderActorView(AActor *actor, bool dontmaplines); void ClearBuffers(); void SetSceneViewport(); void SetupPerspectiveMatrix(); - TriMatrix WorldToClip; RenderPolyScene MainPortal; PolySkyDome Skydome; RenderPolyPlayerSprites PlayerSprites; diff --git a/src/polyrenderer/scene/poly_model.cpp b/src/polyrenderer/scene/poly_model.cpp new file mode 100644 index 0000000000..88064ce97c --- /dev/null +++ b/src/polyrenderer/scene/poly_model.cpp @@ -0,0 +1,255 @@ +/* +** Polygon Doom software renderer +** Copyright (c) 2016 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +** +*/ + +#include +#include "templates.h" +#include "doomdef.h" +#include "sbar.h" +#include "r_data/r_translate.h" +#include "poly_model.h" +#include "polyrenderer/poly_renderer.h" +#include "polyrenderer/scene/poly_light.h" +#include "polyrenderer/poly_renderthread.h" +#include "r_data/r_vanillatrans.h" +#include "actorinlines.h" + +void PolyRenderModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor) +{ + PolyModelRenderer renderer(thread, worldToClip, clipPlane, stencilValue); + renderer.RenderModel(x, y, z, smf, actor); +} + +void PolyRenderHUDModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy) +{ + PolyModelRenderer renderer(thread, worldToClip, clipPlane, stencilValue); + renderer.RenderHUDModel(psp, ofsx, ofsy); +} + +///////////////////////////////////////////////////////////////////////////// + +void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) +{ + ModelActor = actor; + const_cast(objectToWorldMatrix).copy(ObjectToWorld.matrix); +} + +void PolyModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf) +{ + ModelActor = nullptr; +} + +IModelVertexBuffer *PolyModelRenderer::CreateVertexBuffer(bool needindex, bool singleframe) +{ + return new PolyModelVertexBuffer(needindex, singleframe); +} + +void PolyModelRenderer::SetVertexBuffer(IModelVertexBuffer *buffer) +{ +} + +void PolyModelRenderer::ResetVertexBuffer() +{ +} + +VSMatrix PolyModelRenderer::GetViewToWorldMatrix() +{ + TriMatrix swapYZ = TriMatrix::null(); + swapYZ.matrix[0 + 0 * 4] = 1.0f; + swapYZ.matrix[1 + 2 * 4] = 1.0f; + swapYZ.matrix[2 + 1 * 4] = 1.0f; + swapYZ.matrix[3 + 3 * 4] = 1.0f; + + VSMatrix worldToView; + worldToView.loadMatrix((PolyRenderer::Instance()->WorldToView * swapYZ).matrix); + + VSMatrix objectToWorld; + worldToView.inverseMatrix(objectToWorld); + return objectToWorld; +} + +void PolyModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) +{ + ModelActor = actor; + const_cast(objectToWorldMatrix).copy(ObjectToWorld.matrix); +} + +void PolyModelRenderer::EndDrawHUDModel(AActor *actor) +{ + ModelActor = nullptr; +} + +void PolyModelRenderer::SetInterpolation(double interpolation) +{ + InterpolationFactor = (float)interpolation; +} + +void PolyModelRenderer::SetMaterial(FTexture *skin, int clampmode, int translation) +{ + SkinTexture = skin; +} + +void PolyModelRenderer::DrawArrays(int primitiveType, int start, int count) +{ + const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; + + bool foggy = false; + int actualextralight = foggy ? 0 : viewpoint.extralight << 4; + sector_t *sector = ModelActor->Sector; + + bool fullbrightSprite = ((ModelActor->renderflags & RF_FULLBRIGHT) || (ModelActor->flags5 & MF5_BRIGHT)); + int lightlevel = fullbrightSprite ? 255 : ModelActor->Sector->lightlevel + actualextralight; + + TriMatrix swapYZ = TriMatrix::null(); + swapYZ.matrix[0 + 0 * 4] = 1.0f; + swapYZ.matrix[1 + 2 * 4] = 1.0f; + swapYZ.matrix[2 + 1 * 4] = 1.0f; + swapYZ.matrix[3 + 3 * 4] = 1.0f; + + TriMatrix *transform = Thread->FrameMemory->NewObject(); + *transform = WorldToClip * swapYZ * ObjectToWorld; + + PolyDrawArgs args; + args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite); + args.SetTransform(transform); + args.SetFaceCullCCW(true); + args.SetStencilTestValue(StencilValue); + args.SetClipPlane(0, PolyClipPlane()); + args.SetStyle(TriBlendMode::TextureOpaque); + args.SetTexture(SkinTexture); + args.SetDepthTest(true); + args.SetWriteDepth(true); + args.SetWriteStencil(false); + args.DrawArray(Thread, VertexBuffer + start, count); +} + +void PolyModelRenderer::DrawElements(int primitiveType, int numIndices, int elementType, size_t offset) +{ + const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; + + bool foggy = false; + int actualextralight = foggy ? 0 : viewpoint.extralight << 4; + sector_t *sector = ModelActor->Sector; + + bool fullbrightSprite = ((ModelActor->renderflags & RF_FULLBRIGHT) || (ModelActor->flags5 & MF5_BRIGHT)); + int lightlevel = fullbrightSprite ? 255 : ModelActor->Sector->lightlevel + actualextralight; + + TriMatrix swapYZ = TriMatrix::null(); + swapYZ.matrix[0 + 0 * 4] = 1.0f; + swapYZ.matrix[1 + 2 * 4] = 1.0f; + swapYZ.matrix[2 + 1 * 4] = 1.0f; + swapYZ.matrix[3 + 3 * 4] = 1.0f; + + TriMatrix *transform = Thread->FrameMemory->NewObject(); + *transform = WorldToClip * swapYZ * ObjectToWorld; + + PolyDrawArgs args; + args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite); + args.SetTransform(transform); + args.SetFaceCullCCW(true); + args.SetStencilTestValue(StencilValue); + args.SetClipPlane(0, PolyClipPlane()); + args.SetStyle(TriBlendMode::TextureOpaque); + args.SetTexture(SkinTexture); + args.SetDepthTest(true); + args.SetWriteDepth(true); + args.SetWriteStencil(false); + args.DrawElements(Thread, VertexBuffer, IndexBuffer + offset / sizeof(unsigned int), numIndices); +} + +float PolyModelRenderer::GetTimeFloat() +{ + return 0.0f; // (float)gl_frameMS * (float)TICRATE / 1000.0f; +} + +///////////////////////////////////////////////////////////////////////////// + +PolyModelVertexBuffer::PolyModelVertexBuffer(bool needindex, bool singleframe) +{ +} + +PolyModelVertexBuffer::~PolyModelVertexBuffer() +{ +} + +FModelVertex *PolyModelVertexBuffer::LockVertexBuffer(unsigned int size) +{ + mVertexBuffer.Resize(size); + return &mVertexBuffer[0]; +} + +void PolyModelVertexBuffer::UnlockVertexBuffer() +{ +} + +unsigned int *PolyModelVertexBuffer::LockIndexBuffer(unsigned int size) +{ + mIndexBuffer.Resize(size); + return &mIndexBuffer[0]; +} + +void PolyModelVertexBuffer::UnlockIndexBuffer() +{ +} + +void PolyModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) +{ + PolyModelRenderer *polyrenderer = (PolyModelRenderer *)renderer; + + if (true)//if (frame1 == frame2 || size == 0 || polyrenderer->InterpolationFactor == 0.f) + { + TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory(size); + + for (unsigned int i = 0; i < size; i++) + { + vertices[i] = + { + mVertexBuffer[frame1 + i].x, + mVertexBuffer[frame1 + i].y, + mVertexBuffer[frame1 + i].z, + 1.0f, + mVertexBuffer[frame1 + i].u, + mVertexBuffer[frame1 + i].v + }; + } + + polyrenderer->VertexBuffer = vertices; + polyrenderer->IndexBuffer = &mIndexBuffer[0]; + } + else + { + TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory(size); + + float frac = polyrenderer->InterpolationFactor; + for (unsigned int i = 0; i < size; i++) + { + vertices[i].x = mVertexBuffer[frame1 + i].x * (1.0f - frac) + mVertexBuffer[frame2 + i].x * frac; + vertices[i].y = mVertexBuffer[frame1 + i].y * (1.0f - frac) + mVertexBuffer[frame2 + i].y * frac; + vertices[i].z = mVertexBuffer[frame1 + i].z * (1.0f - frac) + mVertexBuffer[frame2 + i].z * frac; + vertices[i].w = 1.0f; + vertices[i].u = mVertexBuffer[frame1 + i].u; + vertices[i].v = mVertexBuffer[frame1 + i].v; + } + + polyrenderer->VertexBuffer = vertices; + polyrenderer->IndexBuffer = &mIndexBuffer[0]; + } +} diff --git a/src/polyrenderer/scene/poly_model.h b/src/polyrenderer/scene/poly_model.h new file mode 100644 index 0000000000..8585be44c8 --- /dev/null +++ b/src/polyrenderer/scene/poly_model.h @@ -0,0 +1,82 @@ +/* +** Polygon Doom software renderer +** Copyright (c) 2016 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +** +*/ + +#pragma once + +#include "polyrenderer/drawers/poly_triangle.h" +#include "gl/data/gl_matrix.h" +#include "gl/models/gl_models.h" + +void PolyRenderModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor); +void PolyRenderHUDModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy); + +class PolyModelRenderer : public FModelRenderer +{ +public: + PolyModelRenderer(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue) : Thread(thread), WorldToClip(worldToClip), ClipPlane(clipPlane), StencilValue(stencilValue) { } + + void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override; + void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override; + IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override; + void SetVertexBuffer(IModelVertexBuffer *buffer) override; + void ResetVertexBuffer() override; + VSMatrix GetViewToWorldMatrix() override; + void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) override; + void EndDrawHUDModel(AActor *actor) override; + void SetInterpolation(double interpolation) override; + void SetMaterial(FTexture *skin, int clampmode, int translation) override; + void DrawArrays(int primitiveType, int start, int count) override; + void DrawElements(int primitiveType, int numIndices, int elementType, size_t offset) override; + float GetTimeFloat() override; + + PolyRenderThread *Thread = nullptr; + const TriMatrix &WorldToClip; + const PolyClipPlane &ClipPlane; + uint32_t StencilValue = 0; + + AActor *ModelActor = nullptr; + TriMatrix ObjectToWorld; + FTexture *SkinTexture = nullptr; + unsigned int *IndexBuffer = nullptr; + TriVertex *VertexBuffer = nullptr; + float InterpolationFactor = 0.0; +}; + +class PolyModelVertexBuffer : public IModelVertexBuffer +{ +public: + PolyModelVertexBuffer(bool needindex, bool singleframe); + ~PolyModelVertexBuffer(); + + FModelVertex *LockVertexBuffer(unsigned int size) override; + void UnlockVertexBuffer() override; + + unsigned int *LockIndexBuffer(unsigned int size) override; + void UnlockIndexBuffer() override; + + void SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) override; + +private: + int mIndexFrame[2]; + TArray mVertexBuffer; + TArray mIndexBuffer; +}; diff --git a/src/polyrenderer/scene/poly_playersprite.cpp b/src/polyrenderer/scene/poly_playersprite.cpp index 8d467ef0a8..017396ffb2 100644 --- a/src/polyrenderer/scene/poly_playersprite.cpp +++ b/src/polyrenderer/scene/poly_playersprite.cpp @@ -29,6 +29,7 @@ #include "polyrenderer/poly_renderer.h" #include "d_player.h" #include "polyrenderer/scene/poly_light.h" +#include "polyrenderer/scene/poly_model.h" EXTERN_CVAR(Bool, r_drawplayersprites) EXTERN_CVAR(Bool, r_deathcamera) @@ -39,6 +40,10 @@ void RenderPolyPlayerSprites::Render(PolyRenderThread *thread) { // This code cannot be moved directly to RenderRemainingSprites because the engine // draws the canvas textures between this call and the final call to RenderRemainingSprites.. + // + // We also can't move it because the model render code relies on it + + renderHUDModel = gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player); const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; @@ -244,6 +249,12 @@ void RenderPolyPlayerSprites::RenderSprite(PolyRenderThread *thread, DPSprite *p sy += wy; } + if (renderHUDModel) + { + PolyRenderHUDModel(thread, PolyRenderer::Instance()->WorldToClip, PolyClipPlane(), 1, pspr, (float)sx, (float)sy); + return; + } + double yaspectMul = 1.2 * ((double)SCREENHEIGHT / SCREENWIDTH) * r_viewwindow.WidescreenRatio; double pspritexscale = viewwindow.centerxwide / 160.0; diff --git a/src/polyrenderer/scene/poly_playersprite.h b/src/polyrenderer/scene/poly_playersprite.h index b07a867155..8e3e9aa7a1 100644 --- a/src/polyrenderer/scene/poly_playersprite.h +++ b/src/polyrenderer/scene/poly_playersprite.h @@ -102,4 +102,5 @@ private: TArray AcceleratedSprites; sector_t tempsec; + bool renderHUDModel = false; }; diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index 8bc1c50549..9ea184c35c 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -29,6 +29,7 @@ #include "polyrenderer/poly_renderer.h" #include "polyrenderer/scene/poly_light.h" #include "polyrenderer/poly_renderthread.h" +#include "polyrenderer/scene/poly_model.h" #include "r_data/r_vanillatrans.h" #include "actorinlines.h" @@ -73,6 +74,17 @@ bool RenderPolySprite::GetLine(AActor *thing, DVector2 &left, DVector2 &right) void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2) { + int spritenum = thing->sprite; + bool isPicnumOverride = thing->picnum.isValid(); + FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); + if (modelframe) + { + const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; + DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac); + PolyRenderModel(thread, worldToClip, clipPlane, stencilValue, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing); + return; + } + DVector2 line[2]; if (!GetLine(thing, line[0], line[1])) return;