/* Coordinate Utility helper class. (C)2018 Marisa Kirisame, UnSX Team. Released under the GNU Lesser General Public License version 3 (or later). See https://www.gnu.org/licenses/lgpl-3.0.txt for its terms. */ Class dt_CoordUtil { // projects a world point onto screen // view matrix setup mostly pulled from gutawer's code static Vector3 WorldToScreen( Vector3 vect, Vector3 eye, double pitch, double yaw, double roll, double vfov ) { double ar = Screen.getWidth()/double(Screen.getHeight()); double fovr = (ar>=1.3)?1.333333:ar; double fov = 2*atan(tan(clamp(vfov,5,170)*0.5)/fovr); float pr = level.pixelstretch; double angx = cos(pitch); double angy = sin(pitch)*pr; double alen = sqrt(angx*angx+angy*angy); double apitch = asin(angy/alen); double ayaw = yaw-90; // rotations dt_Matrix4 mRoll = dt_Matrix4.rotate((0,0,1),roll); dt_Matrix4 mPitch = dt_Matrix4.rotate((1,0,0),apitch); dt_Matrix4 mYaw = dt_Matrix4.rotate((0,-1,0),ayaw); // scaling dt_Matrix4 mScale = dt_Matrix4.identity(); mScale.set(1,1,pr); // YZ swap dt_Matrix4 mYZ = dt_Matrix4.create(); mYZ.set(0,0,1); mYZ.set(2,1,1); mYZ.set(1,2,-1); mYZ.set(3,3,1); // translation dt_Matrix4 mMove = dt_Matrix4.identity(); mMove.set(3,0,-eye.x); mMove.set(3,1,-eye.y); mMove.set(3,2,-eye.z); // perspective dt_Matrix4 mPerspective = dt_Matrix4.perspective(fov,ar,5,65535); // full matrix dt_Matrix4 mView = mRoll.mul(mPitch); mView = mView.mul(mYaw); mView = mView.mul(mScale); mView = mView.mul(mYZ); mView = mView.mul(mMove); dt_Matrix4 mWorldToScreen = mPerspective.mul(mView); return mWorldToScreen.vmat(vect); } // converts a projected screen position to 2D canvas coords // thanks once again to gutawer for making this thing screenblocks-aware // [NEW] added second return value: true if the point has valid depth (i.e.: it's not behind view) // [TODO] handle forced aspect ratio (e.g.: 320x200 scaling) static Vector2, bool ToViewport( Vector3 screenpos, bool scrblocks = true ) { if ( scrblocks ) { int winx, winy, winw, winh; [winx,winy,winw,winh] = Screen.getViewWindow(); int sh = Screen.getHeight(); int ht = sh; int screenblocks = CVar.GetCVar("screenblocks",players[consoleplayer]).getInt(); if ( screenblocks < 10 ) ht = (screenblocks*sh/10)&~7; int bt = sh-(ht+winy-((ht-winh)/2)); return (winx,sh-bt-ht)+((screenpos.x+1)*winw,(-screenpos.y+1)*ht)*0.5, (screenpos.z<=1.0); } else return ((screenpos.x+1)*Screen.getWidth(),(-screenpos.y+1)*Screen.getHeight())*0.5, (screenpos.z<=1.0); } // In Tim Sweeney's own words: "transform by a pitch-yaw-roll rotation" static Vector3, Vector3, Vector3 GetUnAxes( double pitch, double yaw, double roll ) { Vector3 x = (1,0,0), y = (0,-1,0), z = (0,0,1); // y inverted for left-handed result Vector3 a, b, c; // pitch and roll in gzdoom work in reverse compared to UE pitch = -pitch; roll = -roll; // yaw a = (cos(yaw),sin(yaw),0); b = (-sin(yaw),cos(yaw),0); c = (0,0,1); x = (x dot a, x dot b, x dot c); y = (y dot a, y dot b, y dot c); z = (z dot a, z dot b, z dot c); // pitch a = (cos(pitch),0,sin(pitch)); b = (0,1,0); c = (-sin(pitch),0,cos(pitch)); x = (x dot a, x dot b, x dot c); y = (y dot a, y dot b, y dot c); z = (z dot a, z dot b, z dot c); // roll a = (1,0,0); b = (0,cos(roll),-sin(roll)); c = (0,sin(roll),cos(roll)); x = (x dot a, x dot b, x dot c); y = (y dot a, y dot b, y dot c); z = (z dot a, z dot b, z dot c); return x, y, z; } // In Tim Sweeney's own words: "detransform by a pitch-yaw-roll rotation" static Vector3, Vector3, Vector3 GetAxes( double pitch, double yaw, double roll ) { Vector3 x = (1,0,0), y = (0,-1,0), z = (0,0,1); // y inverted for left-handed result Vector3 a, b, c; // pitch and roll in gzdoom work in reverse compared to UE pitch = -pitch; roll = -roll; // inverse roll a = (1,0,0); b = (0,cos(roll),sin(roll)); c = (0,-sin(roll),cos(roll)); x = (x dot a, x dot b, x dot c); y = (y dot a, y dot b, y dot c); z = (z dot a, z dot b, z dot c); // inverse pitch a = (cos(pitch),0,-sin(pitch)); b = (0,1,0); c = (sin(pitch),0,cos(pitch)); x = (x dot a, x dot b, x dot c); y = (y dot a, y dot b, y dot c); z = (z dot a, z dot b, z dot c); // inverse yaw a = (cos(yaw),-sin(yaw),0); b = (sin(yaw),cos(yaw),0); c = (0,0,1); x = (x dot a, x dot b, x dot c); y = (y dot a, y dot b, y dot c); z = (z dot a, z dot b, z dot c); return x, y, z; } }