1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
4+ using System . Runtime . InteropServices ;
5+ using EngineKit . Mathematics ;
6+ using ImGuiNET ;
7+ using Num = System . Numerics ;
8+
19namespace EngineKit . Graphics ;
210
311public readonly record struct VertexInputDescriptor ( VertexInputBindingDescriptor [ ] VertexBindingDescriptors , Label Label )
412{
13+ private static readonly IDictionary < VertexType , VertexInputDescriptor > _vertexTypeToVertexInputDescriptorMapping ;
14+ private static readonly IDictionary < Type , bool > _fieldTypeToNormalizedMapping ;
15+ private static readonly IDictionary < Type , int > _fieldTypeToComponentCountMapping ;
16+ private static readonly IDictionary < Type , DataType > _fieldTypeToDataTypeMapping ;
17+
518 public readonly VertexInputBindingDescriptor [ ] VertexBindingDescriptors = VertexBindingDescriptors ;
619
720 public readonly Label Label = Label ;
21+
22+ static VertexInputDescriptor ( )
23+ {
24+ _fieldTypeToComponentCountMapping = new Dictionary < Type , int >
25+ {
26+ { typeof ( float ) , 1 } ,
27+ { typeof ( Vector2 ) , 2 } ,
28+ { typeof ( Num . Vector2 ) , 2 } ,
29+ { typeof ( Vector3 ) , 3 } ,
30+ { typeof ( Num . Vector3 ) , 3 } ,
31+ { typeof ( Vector4 ) , 4 } ,
32+ { typeof ( Num . Vector4 ) , 4 } ,
33+ { typeof ( uint ) , 4 }
34+ } ;
35+ _fieldTypeToDataTypeMapping = new Dictionary < Type , DataType >
36+ {
37+ { typeof ( float ) , DataType . Float } ,
38+ { typeof ( Vector2 ) , DataType . Float } ,
39+ { typeof ( Num . Vector2 ) , DataType . Float } ,
40+ { typeof ( Vector3 ) , DataType . Float } ,
41+ { typeof ( Num . Vector3 ) , DataType . Float } ,
42+ { typeof ( Vector4 ) , DataType . Float } ,
43+ { typeof ( Num . Vector4 ) , DataType . Float } ,
44+ { typeof ( uint ) , DataType . UnsignedByte }
45+ } ;
46+ _fieldTypeToNormalizedMapping = new Dictionary < Type , bool >
47+ {
48+ { typeof ( float ) , false } ,
49+ { typeof ( Vector2 ) , false } ,
50+ { typeof ( Num . Vector2 ) , false } ,
51+ { typeof ( Vector3 ) , false } ,
52+ { typeof ( Num . Vector3 ) , false } ,
53+ { typeof ( Vector4 ) , false } ,
54+ { typeof ( Num . Vector4 ) , false } ,
55+ { typeof ( uint ) , true }
56+ } ;
57+ _vertexTypeToVertexInputDescriptorMapping = new Dictionary < VertexType , VertexInputDescriptor >
58+ {
59+ { VertexType . Position , BuildVertexInputDescriptorFor < VertexPosition > ( ) } ,
60+ { VertexType . PositionColor , BuildVertexInputDescriptorFor < VertexPositionColor > ( ) } ,
61+ { VertexType . PositionColorUv , BuildVertexInputDescriptorFor < VertexPositionColorUv > ( ) } ,
62+ { VertexType . PositionNormal , BuildVertexInputDescriptorFor < VertexPositionNormal > ( ) } ,
63+ { VertexType . PositionNormalUv , BuildVertexInputDescriptorFor < VertexPositionNormalUv > ( ) } ,
64+ { VertexType . PositionNormalUvTangent , BuildVertexInputDescriptorFor < VertexPositionNormalUvTangent > ( ) } ,
65+ { VertexType . Default , BuildVertexInputDescriptorFor < VertexPositionNormalUvTangent > ( ) } ,
66+ { VertexType . ImGui , BuildVertexInputDescriptorFor < ImDrawVert > ( ) }
67+ } ;
68+ }
69+
70+ public static VertexInputDescriptor ForVertexType ( VertexType vertexType )
71+ {
72+ if ( _vertexTypeToVertexInputDescriptorMapping . TryGetValue ( vertexType , out var vertexInputDescriptor ) )
73+ {
74+ return vertexInputDescriptor ;
75+ }
76+
77+ throw new ArgumentOutOfRangeException ( $ "VertexType { vertexType } has no vertex input descriptor mapping") ;
78+ }
79+
80+ private static VertexInputDescriptor BuildVertexInputDescriptorFor < TVertexType > ( )
81+ {
82+ var vertexType = typeof ( TVertexType ) ;
83+ var vertexTypeAttributes = vertexType . GetFields ( ) ;
84+ var vertexInputBindingDescriptors = vertexTypeAttributes . Select ( ( vertexTypeAttribute , index ) =>
85+ {
86+ var binding = 0u ;
87+ var location = GetLocationFromFieldName ( vertexTypeAttribute . Name ) ;
88+ var dataType = GetDataTypeFromFieldType ( vertexTypeAttribute . FieldType ) ;
89+ var componentCount = GetComponentCountFromFieldType ( vertexTypeAttribute . FieldType ) ;
90+ var offset = ( uint ) Marshal . OffsetOf < TVertexType > ( vertexTypeAttribute . Name ) ;
91+ var isNormalized = GetNormalizedFromFieldType ( vertexTypeAttribute . FieldType ) ;
92+
93+ return new VertexInputBindingDescriptor ( location , binding , dataType , componentCount , offset , isNormalized ) ;
94+ } ) ;
95+ return new VertexInputDescriptor ( vertexInputBindingDescriptors . ToArray ( ) , vertexType . Name ) ;
96+ }
97+
98+ private static uint GetLocationFromFieldName ( string fieldName )
99+ {
100+ return fieldName switch
101+ {
102+ "Position" => 0u ,
103+ "Color" => 1u ,
104+ "Normal" => 2u ,
105+ "Uv" => 3u ,
106+ "Tangent" => 4u ,
107+ _ => GetLocationFromFieldNameForImGui ( fieldName )
108+ } ;
109+ }
110+
111+ private static uint GetLocationFromFieldNameForImGui ( string fieldName )
112+ {
113+ return fieldName . ToLower ( ) switch
114+ {
115+ "pos" => 0u ,
116+ "uv" => 1u ,
117+ "col" => 2u ,
118+ _ => throw new ArgumentOutOfRangeException ( nameof ( fieldName ) , fieldName , null )
119+ } ;
120+ }
121+
122+ private static bool GetNormalizedFromFieldType ( Type fieldType )
123+ {
124+ if ( _fieldTypeToNormalizedMapping . TryGetValue ( fieldType , out var isNormalized ) )
125+ {
126+ return isNormalized ;
127+ }
128+
129+ throw new ArgumentOutOfRangeException ( $ "FieldType { fieldType . Name } has no normalized mapping") ;
130+ }
131+
132+ private static DataType GetDataTypeFromFieldType ( Type fieldType )
133+ {
134+ if ( _fieldTypeToDataTypeMapping . TryGetValue ( fieldType , out var dataType ) )
135+ {
136+ return dataType ;
137+ }
138+
139+ throw new ArgumentOutOfRangeException ( $ "FieldType { fieldType . Name } has no data type mapping") ;
140+ }
141+
142+ private static int GetComponentCountFromFieldType ( Type fieldType )
143+ {
144+ if ( _fieldTypeToComponentCountMapping . TryGetValue ( fieldType , out var componentCount ) )
145+ {
146+ return componentCount ;
147+ }
148+
149+ throw new ArgumentOutOfRangeException ( $ "FieldType { fieldType . Name } has no component count mapping") ;
150+ }
8151}
0 commit comments