1+ using System . Collections . Generic ;
2+ using System . Linq ;
3+ using OpenTK . Graphics . OpenGL ;
4+ using Sledge . Common ;
5+ using Sledge . DataStructures . MapObjects ;
6+ using Sledge . Graphics . Arrays ;
7+
8+ namespace Sledge . DataStructures . Rendering
9+ {
10+ /// <summary>
11+ /// A decal face vertex array collects and stores a VBO for all decal faces in the map.
12+ /// Faces are grouped by texture and then split into subsets for optimised rendering later on.
13+ /// Decals are separated from the solid vertex array because extra decal faces can be added by
14+ /// simple translations, which would break partial updating.
15+ /// </summary>
16+ public class DecalFaceVertexArray
17+ {
18+ private static readonly BeginMode [ ] Modes ;
19+ private static readonly ArraySpecification Specification ;
20+ private static readonly int SpecSize ;
21+
22+ static DecalFaceVertexArray ( )
23+ {
24+ Modes = new [ ] { BeginMode . Triangles , BeginMode . Lines } ;
25+ Specification = new ArraySpecification (
26+ ArrayIndex . Vector3 ( "Position" ) ,
27+ ArrayIndex . Vector3 ( "Normal" ) ,
28+ ArrayIndex . Vector2 ( "Texture" ) ,
29+ ArrayIndex . Vector3 ( "Colour" ) ,
30+ ArrayIndex . Float ( "Selected" ) ) ;
31+ SpecSize = Specification . Indices . Sum ( x => x . Length ) ;
32+ }
33+
34+ public VertexBuffer < float > Array { get ; private set ; }
35+ public List < VertexArraySubset < ITexture > > TextureSubsets { get ; private set ; }
36+ public List < VertexArraySubset < object > > WireframeSubsets { get ; private set ; }
37+ private readonly Dictionary < object , VertexArray < float > > _arrays ;
38+
39+ public void Bind ( object context , int index )
40+ {
41+ if ( ! _arrays . ContainsKey ( context ) )
42+ {
43+ _arrays . Add ( context , new VertexArray < float > ( Array ) ) ;
44+ }
45+ _arrays [ context ] . Bind ( index ) ;
46+ }
47+
48+ public void Unbind ( )
49+ {
50+ VertexArray < float > . Unbind ( ) ;
51+ }
52+
53+ /// <summary>
54+ /// Create a new vertex array for a solid.
55+ /// </summary>
56+ /// <param name="objects">The array objects</param>
57+ public DecalFaceVertexArray ( IEnumerable < MapObject > objects )
58+ {
59+ _arrays = new Dictionary < object , VertexArray < float > > ( ) ;
60+
61+ float [ ] array ;
62+ uint [ ] indices ;
63+ uint [ ] wireframeIndices ;
64+ int count ;
65+ TextureSubsets = new List < VertexArraySubset < ITexture > > ( ) ;
66+ WireframeSubsets = new List < VertexArraySubset < object > > ( ) ;
67+ GetArrayData ( objects , out count , out array , out indices , out wireframeIndices , TextureSubsets , WireframeSubsets ) ;
68+
69+ Array = new VertexBuffer < float > ( Specification , Modes , count , sizeof ( float ) , array , new [ ] { indices , wireframeIndices } ) ;
70+ }
71+
72+ /// <summary>
73+ /// Update the array with new data.
74+ /// </summary>
75+ /// <param name="objects">List containing the data to update</param>
76+ public void Update ( IEnumerable < MapObject > objects )
77+ {
78+ _arrays . Clear ( ) ;
79+ float [ ] array ;
80+ uint [ ] indices ;
81+ uint [ ] wireframeIndices ;
82+ int count ;
83+ TextureSubsets . Clear ( ) ;
84+ WireframeSubsets . Clear ( ) ;
85+ GetArrayData ( objects , out count , out array , out indices , out wireframeIndices , TextureSubsets , WireframeSubsets ) ;
86+
87+ Array . Update ( count , array , new [ ] { indices , wireframeIndices } ) ;
88+ }
89+
90+ /// <summary>
91+ /// Does a loop around the map objects and calculates array data and the subsets
92+ /// </summary>
93+ /// <param name="objects">The objects in the array</param>
94+ /// <param name="count">Outputs the number of verts in the array</param>
95+ /// <param name="array">Outputs the array data</param>
96+ /// <param name="indices">Outputs the triangle drawing indices</param>
97+ /// <param name="wireframeIndices">Outputs the line drawing indices</param>
98+ /// <param name="subsets">The collection of textured subsets to populate</param>
99+ /// <param name="wireframeSubsets">The collection of wireframe subsets to populate</param>
100+ private static void GetArrayData ( IEnumerable < MapObject > objects , out int count , out float [ ] array , out uint [ ] indices , out uint [ ] wireframeIndices , ICollection < VertexArraySubset < ITexture > > subsets , ICollection < VertexArraySubset < object > > wireframeSubsets )
101+ {
102+ var obj = objects . Where ( x => ! x . IsVisgroupHidden && ! x . IsCodeHidden ) . ToList ( ) ;
103+ var faces = obj . OfType < Entity > ( ) . SelectMany ( x => x . GetTexturedFaces ( ) ) . ToList ( ) ;
104+ var indexList = new List < uint > ( ) ;
105+ var wireframeIndexList = new List < uint > ( ) ;
106+ uint index = 0 ;
107+ var idx = 0 ;
108+ var numVerts = faces . Sum ( x => x . Vertices . Count ) ;
109+ array = new float [ SpecSize * numVerts ] ;
110+ var subsetStart = 0 ;
111+ var wireframeSubsetStart = 0 ;
112+ foreach ( var group in faces . GroupBy ( x => new { x . Texture . Texture } ) )
113+ {
114+ foreach ( var face in group )
115+ {
116+ idx = WriteFace ( array , idx , face ) ;
117+ for ( uint i = 1 ; i < face . Vertices . Count - 1 ; i ++ )
118+ {
119+ indexList . Add ( index ) ;
120+ indexList . Add ( index + i ) ;
121+ indexList . Add ( index + i + 1 ) ;
122+ }
123+ for ( uint i = 0 ; i < face . Vertices . Count ; i ++ )
124+ {
125+ var ni = ( uint ) ( ( i + 1 ) % face . Vertices . Count ) ;
126+ wireframeIndexList . Add ( index + i ) ;
127+ wireframeIndexList . Add ( index + ni ) ;
128+ }
129+ index += ( uint ) face . Vertices . Count ;
130+ }
131+
132+ subsets . Add ( new VertexArraySubset < ITexture > ( group . Key . Texture , subsetStart , indexList . Count - subsetStart ) ) ;
133+ subsetStart = indexList . Count ;
134+
135+ wireframeSubsets . Add ( new VertexArraySubset < object > ( null , wireframeSubsetStart , wireframeIndexList . Count - wireframeSubsetStart ) ) ;
136+ wireframeSubsetStart = wireframeIndexList . Count ;
137+ }
138+ indices = indexList . ToArray ( ) ;
139+ wireframeIndices = wireframeIndexList . ToArray ( ) ;
140+ count = indices . Length ;
141+ }
142+
143+ private static int WriteFace ( float [ ] array , int idx , Face face )
144+ {
145+ float nx = ( float ) face . Plane . Normal . DX ,
146+ ny = ( float ) face . Plane . Normal . DY ,
147+ nz = ( float ) face . Plane . Normal . DZ ;
148+ float r = face . Colour . R / 255f ,
149+ g = face . Colour . G / 255f ,
150+ b = face . Colour . B / 255f ;
151+ foreach ( var vert in face . Vertices )
152+ {
153+ array [ idx ++ ] = ( ( float ) vert . Location . DX ) ;
154+ array [ idx ++ ] = ( ( float ) vert . Location . DY ) ;
155+ array [ idx ++ ] = ( ( float ) vert . Location . DZ ) ;
156+ array [ idx ++ ] = ( nx ) ;
157+ array [ idx ++ ] = ( ny ) ;
158+ array [ idx ++ ] = ( nz ) ;
159+ array [ idx ++ ] = ( ( float ) vert . TextureU ) ;
160+ array [ idx ++ ] = ( ( float ) vert . TextureV ) ;
161+ array [ idx ++ ] = ( r ) ;
162+ array [ idx ++ ] = ( g ) ;
163+ array [ idx ++ ] = ( b ) ;
164+ array [ idx ++ ] = ( face . IsSelected || ( face . Parent != null && face . Parent . IsSelected ) ? 1 : 0 ) ;
165+ }
166+ return idx ;
167+ }
168+ }
169+ }
0 commit comments