From 0ac7034397c7452e6ad11a3b20b8ad5e0601d702 Mon Sep 17 00:00:00 2001 From: ponchio Date: Wed, 29 Aug 2012 13:21:22 +0000 Subject: [PATCH] added method to get Projection matrix given near and far. --- vcg/math/camera.h | 476 +++++++++++++++++++++++++--------------------- 1 file changed, 257 insertions(+), 219 deletions(-) diff --git a/vcg/math/camera.h b/vcg/math/camera.h index db624ece..e9dc90d7 100644 --- a/vcg/math/camera.h +++ b/vcg/math/camera.h @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * @@ -141,106 +141,109 @@ template class Camera { public: - typedef S ScalarType; - enum { - PERSPECTIVE = 0, - ORTHO = 1, - ISOMETRIC = 2, - CAVALIERI = 3 - }; + typedef S ScalarType; + enum { + PERSPECTIVE = 0, + ORTHO = 1, + ISOMETRIC = 2, + CAVALIERI = 3 + }; - Camera(): - FocalMm(0.f), - ViewportPx(vcg::Point2(0,0)), - PixelSizeMm(vcg::Point2(0.0,0.0)), - CenterPx(vcg::Point2(0.0,0.0)), - DistorCenterPx(vcg::Point2(0.0,0.0)), - cameraType(0) - { - k[0] = k[1] = k[2] = k[3] = 0; + Camera(): + FocalMm(0.f), + ViewportPx(vcg::Point2(0,0)), + PixelSizeMm(vcg::Point2(0.0,0.0)), + CenterPx(vcg::Point2(0.0,0.0)), + DistorCenterPx(vcg::Point2(0.0,0.0)), + cameraType(0) + { + k[0] = k[1] = k[2] = k[3] = 0; } - //------ camera intrinsics - ScalarType FocalMm; /// Focal Distance: the distance between focal center and image plane. Expressed in mm - Point2 ViewportPx; /// Dimension of the Image Plane (in pixels) - Point2 PixelSizeMm; /// Dimension in mm of a single pixel - Point2 CenterPx; /// Position of the projection of the focal center on the image plane. Expressed in pixels + //------ camera intrinsics + ScalarType FocalMm; /// Focal Distance: the distance between focal center and image plane. Expressed in mm + Point2 ViewportPx; /// Dimension of the Image Plane (in pixels) + Point2 PixelSizeMm; /// Dimension in mm of a single pixel + Point2 CenterPx; /// Position of the projection of the focal center on the image plane. Expressed in pixels - Point2 DistorCenterPx; /// Position of the radial distortion center on the image plane in pixels - S k[4]; /// 1st & 2nd order radial lens distortion coefficient (only the first 2 terms are used) - //------------------------ + Point2 DistorCenterPx; /// Position of the radial distortion center on the image plane in pixels + S k[4]; /// 1st & 2nd order radial lens distortion coefficient (only the first 2 terms are used) + //------------------------ - int cameraType; /// Type of camera: PERSPECTIVE,ORTHO,ISOMETRIC,CAVALIERI + int cameraType; /// Type of camera: PERSPECTIVE,ORTHO,ISOMETRIC,CAVALIERI - void SetOrtho( S l,S r, S b, S t, vcg::Point2 viewport) - { - cameraType = ORTHO; - ViewportPx = viewport; + void SetOrtho( S l,S r, S b, S t, vcg::Point2 viewport) + { + cameraType = ORTHO; + ViewportPx = viewport; - PixelSizeMm[0] = (r-l) / (S)ViewportPx[0]; - PixelSizeMm[1] = (t-b) / (S)ViewportPx[1]; + PixelSizeMm[0] = (r-l) / (S)ViewportPx[0]; + PixelSizeMm[1] = (t-b) / (S)ViewportPx[1]; - CenterPx[0] = -l/(r-l) * (S)ViewportPx[0]; - CenterPx[1] = -b/(t-b) * (S)ViewportPx[1]; - - }; + CenterPx[0] = -l/(r-l) * (S)ViewportPx[0]; + CenterPx[1] = -b/(t-b) * (S)ViewportPx[1]; + + }; - bool IsOrtho() const - { - return ( cameraType == ORTHO ); - } + bool IsOrtho() const + { + return ( cameraType == ORTHO ); + } - //--- Set-up methods + //--- Set-up methods - /// set the camera specifying the perspecive view - inline void SetPerspective(S AngleDeg, S AspectRatio, S Focal, vcg::Point2 Viewport); + /// set the camera specifying the perspecive view + inline void SetPerspective(S AngleDeg, S AspectRatio, S Focal, vcg::Point2 Viewport); - /// set the camera specifying the cavalieri view - inline void SetCavalieri(S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Viewport); + /// set the camera specifying the cavalieri view + inline void SetCavalieri(S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Viewport); - /// set the camera specifying the isometric view - inline void SetIsometric(S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Viewport); + /// set the camera specifying the isometric view + inline void SetIsometric(S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Viewport); - /// set the camera specifying the frustum view - inline void SetFrustum(S dx, S sx, S bt, S tp, S Focal, vcg::Point2 Viewport); - //------------------ + /// set the camera specifying the frustum view + inline void SetFrustum(S dx, S sx, S bt, S tp, S Focal, vcg::Point2 Viewport); + //------------------ - /// returns the frustum - inline void GetFrustum(S & sx, S & dx, S & bt, S & tp, S & nr); + /// returns the projection matrix + vcg::Matrix44 GetMatrix(S nearVal, S farVal); - //--- Space transformation methods - - /// project a point from 3d CAMERA space to the camera local plane - inline vcg::Point2 Project(const vcg::Point3 & p) const; + /// returns the frustum + inline void GetFrustum(S & sx, S & dx, S & bt, S & tp, S & nr); - /// unproject a point from the camera local plane (plus depth) to 3d CAMERA space - inline vcg::Point3 UnProject(const vcg::Point2 & p, const S & d) const; + //--- Space transformation methods - /// transforms local plane coords to vieport (pixel) coords - inline vcg::Point2 LocalToViewportPx(const vcg::Point2 & p) const; - - /// transforms vieport (pixel) coords to local plane coords - inline vcg::Point2 ViewportPxToLocal(const vcg::Point2 & p) const; + /// project a point from 3d CAMERA space to the camera local plane + inline vcg::Point2 Project(const vcg::Point3 & p) const; - /// transforms vieport (pixel) coords to [-1 1] coords - inline vcg::Point2 ViewportPxTo_neg1_1(const vcg::Point2 & p) const; + /// unproject a point from the camera local plane (plus depth) to 3d CAMERA space + inline vcg::Point3 UnProject(const vcg::Point2 & p, const S & d) const; - /// transforms [-1 1] coords to vieport (pixel) coords MICHELE IO - inline vcg::Point2 Neg1_1ToViewportPx(const vcg::Point2 & p) const; + /// transforms local plane coords to vieport (pixel) coords + inline vcg::Point2 LocalToViewportPx(const vcg::Point2 & p) const; - /// transforms local plane coords to [0 1] coords - inline vcg::Point2 LocalTo_0_1(const vcg::Point2 & p) const; + /// transforms vieport (pixel) coords to local plane coords + inline vcg::Point2 ViewportPxToLocal(const vcg::Point2 & p) const; - /// transforms local plane coords to [-1 1] coords - inline vcg::Point2 LocalTo_neg1_1(const vcg::Point2 & p) const; + /// transforms vieport (pixel) coords to [-1 1] coords + inline vcg::Point2 ViewportPxTo_neg1_1(const vcg::Point2 & p) const; - /// transforms an undistorted 2D camera plane point in a distorted 2D camera plane point - vcg::Point2 UndistortedToDistorted(vcg::Point2 u) const; + /// transforms [-1 1] coords to vieport (pixel) coords MICHELE IO + inline vcg::Point2 Neg1_1ToViewportPx(const vcg::Point2 & p) const; - /// transforms a distorted 2D camera plane point in an undistorted 2D camera plane point - vcg::Point2 DistortedToUndistorted(vcg::Point2 d) const; - //-------------------------------- + /// transforms local plane coords to [0 1] coords + inline vcg::Point2 LocalTo_0_1(const vcg::Point2 & p) const; + + /// transforms local plane coords to [-1 1] coords + inline vcg::Point2 LocalTo_neg1_1(const vcg::Point2 & p) const; + + /// transforms an undistorted 2D camera plane point in a distorted 2D camera plane point + vcg::Point2 UndistortedToDistorted(vcg::Point2 u) const; + + /// transforms a distorted 2D camera plane point in an undistorted 2D camera plane point + vcg::Point2 DistortedToUndistorted(vcg::Point2 d) const; + //-------------------------------- }; @@ -249,189 +252,224 @@ public: template vcg::Point2 Camera::Project(const vcg::Point3 & p) const { - vcg::Point2 q = Point2(p[0],p[1]); - vcg::Point2 d = Point2(p[0],p[1]); + vcg::Point2 q = Point2(p[0],p[1]); + vcg::Point2 d = Point2(p[0],p[1]); - if(!IsOrtho()) - { - q[0] *= FocalMm/p.Z(); - q[1] *= FocalMm/p.Z(); - - if(k[0]!=0) - { - vcg::Point2 d; - d=UndistortedToDistorted(q); - q=d; - } - - } + if(!IsOrtho()) + { + q[0] *= FocalMm/p.Z(); + q[1] *= FocalMm/p.Z(); + + if(k[0]!=0) + { + vcg::Point2 d; + d=UndistortedToDistorted(q); + q=d; + } + + } - return q; + return q; } -/// unproject a point from the camera 2d plane [-1,-1]x[1,1] (plus depth) to 3d CAMERA space +template vcg::Matrix44 Camera::GetMatrix(S nearVal, S farVal) { + S left, right, bottom, top, nr; + GetFrustum(left, right, bottom,top, nr); + + if(cameraType == PERSPECTIVE) { + S ratio = nearVal/nr; + left *= ratio; + right *= ratio; + bottom *= ratio; + top *= ratio; + } + vcg::Matrix44 m; + m[0][0] = 2.0*nearVal/(right - left); + m[0][1] = 0; + m[0][2] = (right + left)/(right - left); + m[0][3] = 0; + + m[1][0] = 0; + m[1][1] = 2*nearVal/(top - bottom); + m[1][2] = (top + bottom)/(top - bottom); + m[1][3] = 0; + + m[2][0] = 0; + m[2][1] = 0; + m[2][2] = -(farVal + nearVal)/(farVal - nearVal); + m[2][3] = - 2*farVal*nearVal/(farVal - nearVal); + + m[3][0] = 0; + m[3][1] = 0; + m[3][2] = -1; + m[3][3] = 0; + + return m; +} + +/// unproject a point from the camera 2d plane [-1,-1]x[1,1] (plus depth) to 3d CAMERA space template vcg::Point3 Camera::UnProject(const vcg::Point2 & p, const S & d) const { - vcg::Point3 np = Point3(p[0], p[1], d); + vcg::Point3 np = Point3(p[0], p[1], d); - if(!IsOrtho()) - { - if(k[0]!=0) - { - vcg::Point2 d = Point2(p[0], p[1]); - vcg::Point2 u=DistortedToUndistorted(d); - np[0]=u[0]; - np[1]=u[1]; - } - - np[0] /= FocalMm/d; - np[1] /= FocalMm/d; - } + if(!IsOrtho()) + { + if(k[0]!=0) + { + vcg::Point2 d = Point2(p[0], p[1]); + vcg::Point2 u=DistortedToUndistorted(d); + np[0]=u[0]; + np[1]=u[1]; + } - return np; + np[0] /= FocalMm/d; + np[1] /= FocalMm/d; + } + + return np; } /// transforms local plane coords to vieport (pixel) coords template vcg::Point2 Camera::LocalToViewportPx(const vcg::Point2 & p) const { - vcg::Point2 np; + vcg::Point2 np; - np[0] = (p[0] / PixelSizeMm.X()) + CenterPx.X(); - np[1] = (p[1] / PixelSizeMm.Y()) + CenterPx.Y(); + np[0] = (p[0] / PixelSizeMm.X()) + CenterPx.X(); + np[1] = (p[1] / PixelSizeMm.Y()) + CenterPx.Y(); - return np; + return np; } -/// transforms vieport (pixel) coords to local plane coords +/// transforms vieport (pixel) coords to local plane coords template vcg::Point2 Camera::ViewportPxToLocal(const vcg::Point2 & p) const { - vcg::Point2 ps; - ps[0] = (p[0]-CenterPx.X()) * PixelSizeMm.X(); - ps[1] = (p[1]-CenterPx.Y()) * PixelSizeMm.Y(); - return ps; + vcg::Point2 ps; + ps[0] = (p[0]-CenterPx.X()) * PixelSizeMm.X(); + ps[1] = (p[1]-CenterPx.Y()) * PixelSizeMm.Y(); + return ps; } /// transforms vieport (pixel) coords to [-1 1] coords template vcg::Point2 Camera::ViewportPxTo_neg1_1(const vcg::Point2 & p) const { - vcg::Point2 ps; - ps[0] = 2.0f * ((p[0]-CenterPx.X()) * PixelSizeMm.X())/ ( PixelSizeMm.X() * (S)ViewportPx[0] ); - ps[1] = 2.0f * ((p[1]-CenterPx.Y()) * PixelSizeMm.Y())/ ( PixelSizeMm.Y() * (S)ViewportPx[1] ); - return ps; + vcg::Point2 ps; + ps[0] = 2.0f * ((p[0]-CenterPx.X()) * PixelSizeMm.X())/ ( PixelSizeMm.X() * (S)ViewportPx[0] ); + ps[1] = 2.0f * ((p[1]-CenterPx.Y()) * PixelSizeMm.Y())/ ( PixelSizeMm.Y() * (S)ViewportPx[1] ); + return ps; } /// transforms [-1 1] coords to vieport (pixel) coords MICHELE IO template vcg::Point2 Camera::Neg1_1ToViewportPx(const vcg::Point2 & p) const { - vcg::Point2 ps; - ps[0] = ((PixelSizeMm.X() * (S)ViewportPx[0] *p[0])/(2.0f * PixelSizeMm.X()))+CenterPx.X(); - ps[1] = ((PixelSizeMm.Y() * (S)ViewportPx[1] *p[1])/(2.0f * PixelSizeMm.Y()))+CenterPx.Y(); - return ps; + vcg::Point2 ps; + ps[0] = ((PixelSizeMm.X() * (S)ViewportPx[0] *p[0])/(2.0f * PixelSizeMm.X()))+CenterPx.X(); + ps[1] = ((PixelSizeMm.Y() * (S)ViewportPx[1] *p[1])/(2.0f * PixelSizeMm.Y()))+CenterPx.Y(); + return ps; } /// transforms local plane coords to [0-1] coords template vcg::Point2 Camera::LocalTo_0_1(const vcg::Point2 & p) const { - vcg::Point2 ps; - ps[0] = ( p[0]/PixelSizeMm.X() + CenterPx.X() ) / (S)ViewportPx[0]; - ps[1] = ( p[1]/PixelSizeMm.Y() + CenterPx.Y() ) / (S)ViewportPx[1]; - return ps; + vcg::Point2 ps; + ps[0] = ( p[0]/PixelSizeMm.X() + CenterPx.X() ) / (S)ViewportPx[0]; + ps[1] = ( p[1]/PixelSizeMm.Y() + CenterPx.Y() ) / (S)ViewportPx[1]; + return ps; } /// transforms local plane coords to [-1 1] coords template vcg::Point2 Camera::LocalTo_neg1_1(const vcg::Point2 & p) const { - vcg::Point2 ps; - ps[0] = 2.0f * p[0] / ( PixelSizeMm.X() * (S)ViewportPx[0] ); - ps[1] = 2.0f * p[1] / ( PixelSizeMm.Y() * (S)ViewportPx[1] ); - return ps; + vcg::Point2 ps; + ps[0] = 2.0f * p[0] / ( PixelSizeMm.X() * (S)ViewportPx[0] ); + ps[1] = 2.0f * p[1] / ( PixelSizeMm.Y() * (S)ViewportPx[1] ); + return ps; } /// transforms an undistorted 2D camera plane point in a distorted 2D camera plane point template vcg::Point2 Camera::UndistortedToDistorted(vcg::Point2 u) const - { - vcg::Point2 dis; - vcg::Point2 dc=ViewportPxTo_neg1_1(DistorCenterPx); - const Scalar SQRT3 = Scalar(1.732050807568877293527446341505872366943); - const Scalar CBRT = Scalar(0.33333333333333333333333); - Scalar Ru,Rd,lambda,c,d,Q,R,D,S,T,sinT,cosT; +{ + vcg::Point2 dis; + vcg::Point2 dc=ViewportPxTo_neg1_1(DistorCenterPx); + const Scalar SQRT3 = Scalar(1.732050807568877293527446341505872366943); + const Scalar CBRT = Scalar(0.33333333333333333333333); + Scalar Ru,Rd,lambda,c,d,Q,R,D,S,T,sinT,cosT; - if(((u[0]-dc[0])==0 && (u[1]-dc[1])==0) || k[0] == 0) - { - dis[0] = u[0]; - dis[1] = u[1]; - return dis; - } + if(((u[0]-dc[0])==0 && (u[1]-dc[1])==0) || k[0] == 0) + { + dis[0] = u[0]; + dis[1] = u[1]; + return dis; + } - Ru = hypot ((u[0]-dc[0]), (u[1]-dc[1])); /* SQRT(Xu*Xu+Yu*Yu) */ - c = 1 / k[0]; - d = -c * Ru; + Ru = hypot ((u[0]-dc[0]), (u[1]-dc[1])); /* SQRT(Xu*Xu+Yu*Yu) */ + c = 1 / k[0]; + d = -c * Ru; - Q = c / 3; - R = -d / 2; - if (R<0) - D = pow(Q,3) + sqrt(-R); - else - D = pow(Q,3) + sqrt(R); + Q = c / 3; + R = -d / 2; + if (R<0) + D = pow(Q,3) + sqrt(-R); + else + D = pow(Q,3) + sqrt(R); - if (D >= 0) /* one real root */ - { - D = sqrt(D); - S = pow((R + D),CBRT); - if (R>=D) - T = pow((R - D),CBRT); - else - T = - pow(abs((int)(R - D)),CBRT); //MODIFICATO DA ME - Rd = S + T; + if (D >= 0) /* one real root */ + { + D = sqrt(D); + S = pow((R + D),CBRT); + if (R>=D) + T = pow((R - D),CBRT); + else + T = - pow(abs((int)(R - D)),CBRT); //MODIFICATO DA ME + Rd = S + T; - if (Rd < 0) - Rd = sqrt(-1 / (3 * k[0])); - } - else /* three real roots */ - { - D = sqrt(-D); - S = pow((Scalar)(hypot (R, D)),(Scalar)CBRT); - T = atan2 (D, R) / 3; - //SinCos(T, sinT, cosT); - sinT=sin(T); - cosT=cos(T); + if (Rd < 0) + Rd = sqrt(-1 / (3 * k[0])); + } + else /* three real roots */ + { + D = sqrt(-D); + S = pow((Scalar)(hypot (R, D)),(Scalar)CBRT); + T = atan2 (D, R) / 3; + //SinCos(T, sinT, cosT); + sinT=sin(T); + cosT=cos(T); - /* the larger positive root is 2*S*cos(T) */ - /* the smaller positive root is -S*cos(T) + SQRT(3)*S*sin(T) */ - /* the negative root is -S*cos(T) - SQRT(3)*S*sin(T) */ - Rd = -S * cosT + SQRT3 * S * sinT; /* use the smaller positive root */ - } + /* the larger positive root is 2*S*cos(T) */ + /* the smaller positive root is -S*cos(T) + SQRT(3)*S*sin(T) */ + /* the negative root is -S*cos(T) - SQRT(3)*S*sin(T) */ + Rd = -S * cosT + SQRT3 * S * sinT; /* use the smaller positive root */ + } - lambda = Rd / Ru; + lambda = Rd / Ru; - dis[0] = u[0] * lambda; - dis[1] = u[1] * lambda; + dis[0] = u[0] * lambda; + dis[1] = u[1] * lambda; - return dis; - } + return dis; +} /// transforms a distorted 2D camera plane point in an undistorted 2D camera plane point template vcg::Point2 Camera::DistortedToUndistorted(vcg::Point2 d) const - { - vcg::Point2 u; - vcg::Point2 dc=ViewportPxTo_neg1_1(DistorCenterPx); - S r=sqrt(pow((d[0]-dc[0]),2)+pow((d[1]-dc[1]),2)); - u[0]=d[0]*(1-k[0]*r*r); - u[1]=d[1]*(1-k[0]*r*r); +{ + vcg::Point2 u; + vcg::Point2 dc=ViewportPxTo_neg1_1(DistorCenterPx); + S r=sqrt(pow((d[0]-dc[0]),2)+pow((d[1]-dc[1]),2)); + u[0]=d[0]*(1-k[0]*r*r); + u[1]=d[1]*(1-k[0]*r*r); - return u; + return u; - } +} //--- basic camera setup (GL-like) @@ -440,36 +478,36 @@ vcg::Point2 Camera::DistortedToUndistorted(vcg::Point2 d) const template void Camera::SetPerspective( S AngleDeg, S AspectRatio, S Focal, vcg::Point2 Viewport) { - cameraType = PERSPECTIVE; - S halfsize[2]; + cameraType = PERSPECTIVE; + S halfsize[2]; - halfsize[1] = tan(math::ToRad(AngleDeg/2.0f)) * Focal; - halfsize[0] = halfsize[1]*AspectRatio; + halfsize[1] = tan(math::ToRad(AngleDeg/2.0f)) * Focal; + halfsize[0] = halfsize[1]*AspectRatio; - SetFrustum(-halfsize[0],halfsize[0],-halfsize[1],halfsize[1],Focal,Viewport); + SetFrustum(-halfsize[0],halfsize[0],-halfsize[1],halfsize[1],Focal,Viewport); } /// set the camera specifying the frustum view template void Camera::SetFrustum( S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Viewport) { - S vp[2]; - vp[0] = dx-sx; - vp[1] = tp-bt; + S vp[2]; + vp[0] = dx-sx; + vp[1] = tp-bt; - ViewportPx[0] = Viewport[0]; - if(vp[1] != -1) - ViewportPx[1] = Viewport[1]; // the user specified the viewport - else - ViewportPx[1] = ViewportPx[0]; // default viewport + ViewportPx[0] = Viewport[0]; + if(vp[1] != -1) + ViewportPx[1] = Viewport[1]; // the user specified the viewport + else + ViewportPx[1] = ViewportPx[0]; // default viewport - PixelSizeMm[0] = vp[0] / (S)Viewport[0]; - PixelSizeMm[1] = vp[1] / (S)Viewport[1]; + PixelSizeMm[0] = vp[0] / (S)Viewport[0]; + PixelSizeMm[1] = vp[1] / (S)Viewport[1]; - CenterPx[0] = -sx/vp[0] * (S)Viewport[0]; - CenterPx[1] = -bt/vp[1] * (S)Viewport[1]; + CenterPx[0] = -sx/vp[0] * (S)Viewport[0]; + CenterPx[1] = -bt/vp[1] * (S)Viewport[1]; - FocalMm =Focal; + FocalMm =Focal; } //--- special cameras setup @@ -478,29 +516,29 @@ void Camera::SetFrustum( S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Vi template void Camera::SetCavalieri(S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Viewport) { - cameraType = CAVALIERI; - SetFrustum(sx, dx, bt, tp, Focal,Viewport); + cameraType = CAVALIERI; + SetFrustum(sx, dx, bt, tp, Focal,Viewport); } /// set the camera specifying the isometric view template void Camera::SetIsometric(S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Viewport) { - cameraType = ISOMETRIC; - SetFrustum(sx, dx, bt, tp, Focal,Viewport); + cameraType = ISOMETRIC; + SetFrustum(sx, dx, bt, tp, Focal,Viewport); } /// returns the frustum template void Camera:: GetFrustum( S & sx, S & dx, S & bt, S & tp, S & nr) { - dx = CenterPx.X()* PixelSizeMm.X(); //scaled center - sx = -( (S)ViewportPx.X() - CenterPx.X() ) * PixelSizeMm.X(); + dx = CenterPx.X()* PixelSizeMm.X(); //scaled center + sx = -( (S)ViewportPx.X() - CenterPx.X() ) * PixelSizeMm.X(); - bt = -CenterPx.Y()* PixelSizeMm.Y(); - tp = ( (S)ViewportPx.Y() - CenterPx.Y() ) * PixelSizeMm.Y(); + bt = -CenterPx.Y()* PixelSizeMm.Y(); + tp = ( (S)ViewportPx.Y() - CenterPx.Y() ) * PixelSizeMm.Y(); - nr = FocalMm; + nr = FocalMm; } }