// gutamatics projection data caching and other functions from SWWM GZ Struct dt_ProjectionData { dt_GM_Matrix wtc; int viewx, viewy, vieww, viewh; } Class dt_Utility { // gutamatics caching static clearscope void PrepareProjData( out dt_ProjectionData d, Vector3 viewpos, double angle, double pitch, double roll, double fov ) { double aspect = Screen.GetAspectRatio(); // vertical fov double fovratio = (aspect>=1.3)?1.333333:aspect; double fovy = 2.*atan(tan(clamp(fov,5,170)/2.)/fovratio); // world→clip matrix dt_GM_Matrix view = dt_GM_Matrix.view(viewpos,angle,pitch,roll); dt_GM_Matrix perp = dt_GM_Matrix.perspective(fovy,aspect,5,65535); d.wtc = perp.multiplyMatrix(view); // screen coord data int sblocks = CVar.FindCVar('screenblocks').GetInt(); int viewx, viewy, vieww, viewh; [viewx, viewy, vieww, viewh] = Screen.GetViewWindow(); int sh = Screen.GetHeight(); int h = sh; if ( sblocks < 10 ) h = (sblocks*sh/10)&~7; int bottom = sh-(h+viewy-((h-viewh)/2)); d.viewx = viewx; d.viewy = sh-bottom-h; d.vieww = vieww; d.viewh = h; } static clearscope Vector3 ProjectPoint( dt_ProjectionData d, Vector3 worldpos ) { return d.wtc.multiplyVector3(worldpos).asVector3(); } static clearscope Vector2 NDCToViewport( dt_ProjectionData d, Vector3 ndc ) { return (d.viewx,d.viewy)+(((ndc.x+1)*d.vieww)/2,((-ndc.y+1)*d.viewh)/2); } // checks if a point is inside the viewport static clearscope bool TestScreenBounds( dt_ProjectionData d, Vector2 vpos ) { return ((vpos.x == clamp(vpos.x,d.viewx,d.viewx+d.vieww)) && (vpos.y == clamp(vpos.y,d.viewy,d.viewy+d.viewh))); } static clearscope Vector3 Vec3FromAngle( double angle, double pitch ) { return (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch)); } static clearscope Vector3 CircleOffset( Vector3 y, Vector3 z, double angle, double radius ) { return (y*cos(angle)*radius+z*sin(angle)*radius); } static clearscope Vector3 ConeSpread( Vector3 x, Vector3 y, Vector3 z, double angle, double spread ) { return (x+y*cos(angle)*spread+z*sin(angle)*spread).unit(); } static clearscope Vector3, Vector3, Vector3 GetAxes( double angle, double pitch, double roll ) { Vector3 x = (1,0,0), y = (0,-1,0), z = (0,0,1); Quat r = Quat.FromAngles(angle,pitch,roll); return r*x, r*y, r*z; } }