@@ -14,43 +14,87 @@ public static class Utilities
1414 public const float DefaultFarZ = 100.0f ;
1515 public const float DefaultOffset = 0f ;
1616
17- public static Vector4 FovfToTanFovVector ( this Fovf fovf ) => new
18- (
19- MathF . Tan ( fovf . AngleLeft ) ,
20- MathF . Tan ( fovf . AngleRight ) ,
21- MathF . Tan ( fovf . AngleUp ) ,
22- MathF . Tan ( fovf . AngleDown )
23- ) ;
24-
25- public static Matrix4x4 FovfToMatrix
26- (
27- this Fovf fovf ,
28- float nearZ = DefaultNearZ ,
29- float farZ = DefaultFarZ ,
30- float offsetZ = DefaultOffset
31- )
32- {
33- var tanFov = fovf . FovfToTanFovVector ( ) ;
34- var tanAngleWidth = tanFov . Y - tanFov . X ;
35- var tanAngleHeight = tanFov . W - tanFov . Z ;
36- return new
17+ public static Matrix4x4 ToView ( this Posef pose )
18+ => Matrix4x4 . Identity
19+ * Matrix4x4 . CreateTranslation ( Unsafe . As < Vector3f , Vector3 > ( ref pose . Position ) )
20+ * Matrix4x4 . CreateFromQuaternion ( Unsafe . As < Quaternionf , Quaternion > ( ref pose . Orientation ) ) ;
21+
22+ public static Matrix4x4
23+ ToProjection
3724 (
38- 2 / tanAngleWidth , 0 , ( tanFov . Y + tanFov . X ) / tanAngleWidth , 0 ,
39- 0 , 2 / tanAngleHeight , ( tanFov . Z + tanFov . W ) / tanAngleHeight , 0 ,
40- 0 , 0 , - ( farZ + offsetZ ) / ( farZ - nearZ ) , - ( farZ * ( nearZ + offsetZ ) ) / ( farZ - nearZ ) ,
41- 0 , 0 , - 1 , 0
42- ) ;
43- }
25+ this Fovf fov ,
26+ bool isGlSpace = true ,
27+ float nearZ = DefaultNearZ ,
28+ float farZ = DefaultFarZ
29+ )
30+ {
31+ Matrix4x4 result = default ;
4432
45- public static Quaternion QuaternionfToQuaternion ( this Quaternionf quat )
46- => Unsafe . As < Quaternionf , Quaternion > ( ref quat ) ;
33+ var tanAngleLeft = MathF . Tan ( fov . AngleLeft ) ;
34+ var tanAngleRight = MathF . Tan ( fov . AngleRight ) ;
4735
48- public static Vector3 Vector3fToVector3 ( this Vector3f vec )
49- => Unsafe . As < Vector3f , Vector3 > ( ref vec ) ;
36+ var tanAngleDown = MathF . Tan ( fov . AngleDown ) ;
37+ var tanAngleUp = MathF . Tan ( fov . AngleUp ) ;
5038
51- public static Matrix4x4 PosefToMatrix ( this Posef pose )
52- => Matrix4x4 . Identity
53- * Matrix4x4 . CreateTranslation ( pose . Position . Vector3fToVector3 ( ) )
54- * Matrix4x4 . CreateFromQuaternion ( pose . Orientation . QuaternionfToQuaternion ( ) ) ;
39+ var tanAngleWidth = tanAngleRight - tanAngleLeft ;
40+
41+ // Set to tanAngleDown - tanAngleUp for a clip space with positive Y
42+ // down (Vulkan). Set to tanAngleUp - tanAngleDown for a clip space with
43+ // positive Y up (OpenGL / D3D / Metal).
44+ var tanAngleHeight = ! isGlSpace ? tanAngleDown - tanAngleUp : tanAngleUp - tanAngleDown ;
45+
46+ // Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES).
47+ // Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal).
48+ var offsetZ = isGlSpace ? nearZ : 0 ;
49+
50+ if ( farZ <= nearZ )
51+ {
52+ // place the far plane at infinity
53+ result . M11 = 2 / tanAngleWidth ;
54+ result . M21 = 0 ;
55+ result . M31 = ( tanAngleRight + tanAngleLeft ) / tanAngleWidth ;
56+ result . M41 = 0 ;
57+
58+ result . M11 = 0 ;
59+ result . M21 = 2 / tanAngleHeight ;
60+ result . M31 = ( tanAngleUp + tanAngleDown ) / tanAngleHeight ;
61+ result . M41 = 0 ;
62+
63+ result . M13 = 0 ;
64+ result . M23 = 0 ;
65+ result . M33 = - 1 ;
66+ result . M43 = - ( nearZ + offsetZ ) ;
67+
68+ result . M14 = 0 ;
69+ result . M24 = 0 ;
70+ result . M34 = - 1 ;
71+ result . M44 = 0 ;
72+ }
73+ else
74+ {
75+ // normal projection
76+ result . M11 = 2 / tanAngleWidth ;
77+ result . M21 = 0 ;
78+ result . M31 = ( tanAngleRight + tanAngleLeft ) / tanAngleWidth ;
79+ result . M41 = 0 ;
80+
81+ result . M12 = 0 ;
82+ result . M22 = 2 / tanAngleHeight ;
83+ result . M32 = ( tanAngleUp + tanAngleDown ) / tanAngleHeight ;
84+ result . M42 = 0 ;
85+
86+ result . M13 = 0 ;
87+ result . M23 = 0 ;
88+ result . M33 = - ( farZ + offsetZ ) / ( farZ - nearZ ) ;
89+ result . M43 = - ( farZ * ( nearZ + offsetZ ) ) / ( farZ - nearZ ) ;
90+
91+ result . M14 = 0 ;
92+ result . M24 = 0 ;
93+ result . M34 = - 1 ;
94+ result . M44 = 0 ;
95+ }
96+
97+ return result ;
98+ }
5599 }
56100}
0 commit comments