diff --git a/src/swrenderer/scene/r_viewport.cpp b/src/swrenderer/scene/r_viewport.cpp index 1fc4494a8..24413b3c5 100644 --- a/src/swrenderer/scene/r_viewport.cpp +++ b/src/swrenderer/scene/r_viewport.cpp @@ -148,10 +148,6 @@ namespace swrenderer FocalLengthX = CenterX / FocalTangent; FocalLengthY = FocalLengthX * YaspectMul; - // This is 1/FocalTangent before the widescreen extension of FOV. - viewingrangerecip = FLOAT2FIXED(1. / tan(FieldOfView.Radians() / 2)); - - // Now generate xtoviewangle for sky texture mapping. // [RH] Do not generate viewangletox, because texture mapping is no // longer done with trig, so it's not needed. @@ -167,4 +163,46 @@ namespace swrenderer xtoviewangle[i] = 0 - xtoviewangle[viewwidth - i - 1]; } } + + DVector2 RenderViewport::PointWorldToView(const DVector2 &worldPos) const + { + double translatedX = worldPos.X - ViewPos.X; + double translatedY = worldPos.Y - ViewPos.Y; + return { + translatedX * ViewSin - translatedY * ViewCos, + translatedX * ViewTanCos + translatedY * ViewTanSin + }; + } + + DVector3 RenderViewport::PointWorldToView(const DVector3 &worldPos) const + { + double translatedX = worldPos.X - ViewPos.X; + double translatedY = worldPos.Y - ViewPos.Y; + double translatedZ = worldPos.Z - ViewPos.Z; + return { + translatedX * ViewSin - translatedY * ViewCos, + translatedZ, + translatedX * ViewTanCos + translatedY * ViewTanSin + }; + } + + DVector3 RenderViewport::PointWorldToScreen(const DVector3 &worldPos) const + { + return PointViewToScreen(PointWorldToView(worldPos)); + } + + DVector3 RenderViewport::PointViewToScreen(const DVector3 &viewPos) const + { + double screenX = CenterX + viewPos.X / viewPos.Z * CenterX; + double screenY = CenterY - viewPos.Y / viewPos.Z * InvZtoScale; + return { screenX, screenY, viewPos.Z }; + } + + DVector2 RenderViewport::ScaleViewToScreen(const DVector2 &scale, double viewZ, bool pixelstretch) const + { + double screenScaleX = scale.X / viewZ * CenterX; + double screenScaleY = scale.Y / viewZ * InvZtoScale; + if (!pixelstretch) screenScaleY /= YaspectMul; + return { screenScaleX, screenScaleY }; + } } diff --git a/src/swrenderer/scene/r_viewport.h b/src/swrenderer/scene/r_viewport.h index ea5436980..d89dbec6e 100644 --- a/src/swrenderer/scene/r_viewport.h +++ b/src/swrenderer/scene/r_viewport.h @@ -27,7 +27,7 @@ namespace swrenderer void SetupFreelook(); DCanvas *RenderTarget = nullptr; - fixed_t viewingrangerecip = 0; + double FocalLengthX = 0.0; double FocalLengthY = 0.0; double InvZtoScale = 0.0; @@ -48,6 +48,13 @@ namespace swrenderer bool RenderingToCanvas() const { return RenderTarget != screen; } + DVector3 PointWorldToView(const DVector3 &worldPos) const; + DVector3 PointWorldToScreen(const DVector3 &worldPos) const; + DVector3 PointViewToScreen(const DVector3 &viewPos) const; + + DVector2 PointWorldToView(const DVector2 &worldPos) const; + DVector2 ScaleViewToScreen(const DVector2 &scale, double viewZ, bool pixelstretch = true) const; + private: void InitTextureMapping(); void SetupBuffer(); diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index 6da831163..7f30257bb 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -318,35 +318,18 @@ namespace swrenderer { auto viewport = RenderViewport::Instance(); - double viewX, viewY, viewZ; - if (viewspace) - { - viewX = origin.X; - viewY = origin.Y; - viewZ = origin.Z; - } - else // world space - { - double translatedX = origin.X - ViewPos.X; - double translatedY = origin.Y - ViewPos.Y; - double translatedZ = origin.Z - ViewPos.Z; - viewX = translatedX * ViewSin - translatedY * ViewCos; - viewY = translatedZ; - viewZ = translatedX * ViewTanCos + translatedY * ViewTanSin; - } + DVector3 viewPos = viewport->PointWorldToView(origin); - if (viewZ < 0.01f) + if (viewPos.Z < 0.01f) return; - double screenX = viewport->CenterX + viewX / viewZ * viewport->CenterX; - double screenY = viewport->CenterY - viewY / viewZ * viewport->InvZtoScale; - double screenExtentX = extentX / viewZ * viewport->CenterX; - double screenExtentY = pixelstretch ? screenExtentX * viewport->YaspectMul : screenExtentX; + DVector3 screenPos = viewport->PointViewToScreen(viewPos); + DVector2 screenExtent = viewport->ScaleViewToScreen({ extentX, extentY }, viewPos.Z, pixelstretch); - int x1 = MAX((int)(screenX - screenExtentX), 0); - int x2 = MIN((int)(screenX + screenExtentX + 0.5f), viewwidth - 1); - int y1 = MAX((int)(screenY - screenExtentY), 0); - int y2 = MIN((int)(screenY + screenExtentY + 0.5f), viewheight - 1); + int x1 = MAX((int)(screenPos.X - screenExtent.X), 0); + int x2 = MIN((int)(screenPos.X + screenExtent.X + 0.5f), viewwidth - 1); + int y1 = MAX((int)(screenPos.Y - screenExtent.Y), 0); + int y2 = MIN((int)(screenPos.Y + screenExtent.Y + 0.5f), viewheight - 1); int pixelsize = viewport->RenderTarget->IsBgra() ? 4 : 1;