diff --git a/src/swrenderer/things/r_model.cpp b/src/swrenderer/things/r_model.cpp index 84f4de39d..8040797b5 100644 --- a/src/swrenderer/things/r_model.cpp +++ b/src/swrenderer/things/r_model.cpp @@ -67,7 +67,7 @@ namespace swrenderer void RenderModel::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) { - SWModelRenderer renderer(thread); + SWModelRenderer renderer(thread, clip3DFloor); renderer.RenderModel(x, y, z, smf, actor); } @@ -75,13 +75,13 @@ namespace swrenderer void RenderHUDModel(RenderThread *thread, DPSprite *psp, float ofsx, float ofsy) { - SWModelRenderer renderer(thread); + SWModelRenderer renderer(thread, Fake3DTranslucent()); renderer.RenderHUDModel(psp, ofsx, ofsy); } ///////////////////////////////////////////////////////////////////////////// - SWModelRenderer::SWModelRenderer(RenderThread *thread) : Thread(thread) + SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor) : Thread(thread), Clip3DFloor(clip3DFloor) { if (polymodelsInUse) { @@ -94,6 +94,39 @@ namespace swrenderer { ModelActor = actor; const_cast(objectToWorldMatrix).copy(ObjectToWorld.Matrix); + + ClipTop = {}; + ClipBottom = {}; + if (Clip3DFloor.clipTop || Clip3DFloor.clipBottom) + { + // Convert 3d floor clipping planes from world to object space + + VSMatrix inverseMat; + const_cast(objectToWorldMatrix).inverseMatrix(inverseMat); + Mat4f worldToObject; + inverseMat.copy(worldToObject.Matrix); + + // Note: Y and Z is swapped here + + Vec4f one = worldToObject * Vec4f(0.0f, 1.0f, 0.0f, 1.0f); + Vec4f zero = worldToObject * Vec4f(0.0f, 0.0f, 0.0f, 1.0f); + Vec4f up = { one.X - zero.X, one.Y - zero.Y, one.Z - zero.Z }; + + if (Clip3DFloor.clipTop) + { + Vec4f p = worldToObject * Vec4f(0.0f, Clip3DFloor.sclipTop, 0.0f, 1.0f); + float d = up.X * p.X + up.Y * p.Y + up.Z * p.Z; + ClipTop = { -up.X, -up.Y, -up.Z, d }; + } + + if (Clip3DFloor.clipBottom) + { + Vec4f p = worldToObject * Vec4f(0.0f, Clip3DFloor.sclipBottom, 0.0f, 1.0f); + float d = up.X * p.X + up.Y * p.Y + up.Z * p.Z; + ClipBottom = { up.X, up.Y, up.Z, -d }; + } + } + SetTransform(); } @@ -154,6 +187,8 @@ namespace swrenderer { ModelActor = actor; const_cast(objectToWorldMatrix).copy(ObjectToWorld.Matrix); + ClipTop = {}; + ClipBottom = {}; SetTransform(); PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, true); } @@ -198,7 +233,6 @@ namespace swrenderer PolyDrawArgs args; args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, Thread->Light->SpriteGlobVis(foggy), fullbrightSprite); - args.SetClipPlane(0, PolyClipPlane()); args.SetStyle(TriBlendMode::TextureOpaque); if (Thread->Viewport->RenderTarget->IsBgra()) @@ -209,6 +243,10 @@ namespace swrenderer args.SetDepthTest(true); args.SetWriteDepth(true); args.SetWriteStencil(false); + args.SetClipPlane(0, PolyClipPlane()); + args.SetClipPlane(1, ClipTop); + args.SetClipPlane(2, ClipBottom); + args.DrawArray(Thread->DrawQueue, VertexBuffer + start, count); } @@ -225,7 +263,6 @@ namespace swrenderer PolyDrawArgs args; args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, Thread->Light->SpriteGlobVis(foggy), fullbrightSprite); - args.SetClipPlane(0, PolyClipPlane()); args.SetStyle(TriBlendMode::TextureOpaque); if (Thread->Viewport->RenderTarget->IsBgra()) @@ -236,6 +273,10 @@ namespace swrenderer args.SetDepthTest(true); args.SetWriteDepth(true); args.SetWriteStencil(false); + args.SetClipPlane(0, PolyClipPlane()); + args.SetClipPlane(1, ClipTop); + args.SetClipPlane(2, ClipBottom); + args.DrawElements(Thread->DrawQueue, VertexBuffer, IndexBuffer + offset / sizeof(unsigned int), numIndices); } diff --git a/src/swrenderer/things/r_model.h b/src/swrenderer/things/r_model.h index 5d8f7b688..0519d5588 100644 --- a/src/swrenderer/things/r_model.h +++ b/src/swrenderer/things/r_model.h @@ -52,7 +52,7 @@ namespace swrenderer class SWModelRenderer : public FModelRenderer { public: - SWModelRenderer(RenderThread *thread); + SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor); void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override; void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override; @@ -70,9 +70,11 @@ namespace swrenderer void SetTransform(); RenderThread *Thread = nullptr; + Fake3DTranslucent Clip3DFloor; AActor *ModelActor = nullptr; Mat4f ObjectToWorld; + PolyClipPlane ClipTop, ClipBottom; FTexture *SkinTexture = nullptr; unsigned int *IndexBuffer = nullptr; TriVertex *VertexBuffer = nullptr; diff --git a/src/swrenderer/things/r_playersprite.cpp b/src/swrenderer/things/r_playersprite.cpp index 722576a5d..acb521500 100644 --- a/src/swrenderer/things/r_playersprite.cpp +++ b/src/swrenderer/things/r_playersprite.cpp @@ -94,8 +94,7 @@ namespace swrenderer (r_deathcamera && Thread->Viewport->viewpoint.camera->health <= 0)) return; - if (r_models && gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player)) - renderHUDModel = true; + renderHUDModel = r_models && gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player); FDynamicColormap *basecolormap; CameraLight *cameraLight = CameraLight::Instance();