#region Using ステートメント using Microsoft.Xna.Framework.Graphics; #endregion namespace Demo { /// /// 連続書き込み用の頂点バッファ管理クラス /// /// /// 動的頂点バッファへの書き込みは書き込み先がGPUの読み込み中の場所と /// バッティングしないよう注意する必要がある。 /// /// http://blogs.msdn.com/ito/archive/2009/03/25/how-gpus-works-01.aspx /// /// 管理自体は簡単でも余計な変数や /// 処理が増えるので、その処理をこのクラスで管理している。 /// DynamicVertexBufferとの違いはSetData>T<をメソッドが書き込んだ /// オフセットを返すのでその値を以下の様に使うことができる /// /// int offset = writableVB.WriteData( ... ); /// GraphicsDevice.SetVertexBuffer(writableVB.VertexBuffer, offset); /// /// public class WritableVertexBuffer where T : struct { /// /// バッファを取得する /// public DynamicVertexBuffer VertexBuffer { get { return vb; } } /// /// WritableVertexBufferの生成 /// /// この頂点バッファに関連付けるグラフィックデバイス /// この頂点バッファに格納できる最大要素数 public WritableVertexBuffer(GraphicsDevice device, int maxElementCount) { this.vb = new DynamicVertexBuffer(device, typeof(T), maxElementCount, BufferUsage.WriteOnly); this.maxElementCount = maxElementCount; } /// /// 頂点データの書き込み /// /// 書き込む頂点データ配列 /// 書き込んだデータの先頭オフセット public int WriteData(T[] vertices) { return SetData(vertices, 0, vertices.Length); } /// /// 頂点データの書き込み /// /// 書き込む頂点データ配列 /// 書き込むデータの先頭インデックス /// 書き込む要素数 /// 書き込んだデータの先頭オフセット public int SetData(T[] vertices, int startIndex, int elementCount) { // 頂点データの書き込み int position = currentPosition; SetDataOptions hint = SetDataOptions.NoOverwrite; // 最大要素数を超えるようであれば、頂点バッファの先頭に移動し、Dicardオプションを使う。 if (position + elementCount > maxElementCount) { position = 0; hint = SetDataOptions.Discard; } // 頂点データを頂点バッファへ書き込む int strideSize = vb.VertexDeclaration.VertexStride; vb.SetData(position * strideSize, vertices, startIndex, elementCount, strideSize, hint); currentPosition = position + elementCount; return position; } // 実際の頂点バッファ DynamicVertexBuffer vb; // 現在の書き込み位置 int currentPosition; // 最大頂点数 int maxElementCount; } }