Add some transform helpers on RenderViewport

This commit is contained in:
Magnus Norddahl 2017-02-01 23:23:10 +01:00
parent d91e6ccece
commit 69b7312099
3 changed files with 58 additions and 30 deletions

View file

@ -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 };
}
}

View file

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

View file

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