private RawList <T> GetVertexList <T>() where T : struct, IVertexData { // Fast path: Retrieve and return int typeIndex = VertexDeclaration.Get <T>().TypeIndex; RawList <T> vertexList = null; if (typeIndex < this.vertexDataSlots.Length && (vertexList = this.vertexDataSlots[typeIndex].Vertices as RawList <T>) != null) { return(vertexList); } // Slow / init path else { // Allocate slot for vertex type if (typeIndex >= this.vertexDataSlots.Length) { Array.Resize(ref this.vertexDataSlots, typeIndex + 1); } this.usedSlotCount = Math.Max(this.usedSlotCount, typeIndex + 1); // Init batch storage for vertex type if (this.vertexDataSlots[typeIndex].Batches == null) { this.vertexDataSlots[typeIndex].Batches = new List <IVertexBatch>(); this.vertexDataSlots[typeIndex].Batches.Add(new VertexBatch <T>()); } // Assign current vertex batch for fast access VertexBatch <T> batch = (VertexBatch <T>) this.vertexDataSlots[typeIndex].Batches[0]; this.vertexDataSlots[typeIndex].Vertices = batch.Vertices; this.vertexDataSlots[typeIndex].ActiveBatchCount = 1; return(batch.Vertices); } }
/// <summary> /// Clears this buffer from all previous vertex data and re-initializes it /// with the specified number of vertices. /// </summary> public void SetupVertexData <T>(int count) where T : struct, IVertexData { this.EnsureNativeVertex(); this.vertexCount = count; this.vertexType = VertexDeclaration.Get <T>(); this.nativeVertex.SetupEmpty <T>(count); }
/// <summary> /// Uploads the specified vertices to this buffer, replacing all previous contents. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="data"></param> /// <param name="index"></param> /// <param name="count"></param> public void LoadVertexData <T>(T[] data, int index, int count) where T : struct, IVertexData { this.EnsureNativeVertex(); this.vertexCount = count; this.vertexType = VertexDeclaration.Get <T>(); this.nativeVertex.LoadData(data, index, count); }
/// <summary> /// Retrieves the stored vertex batch that matches the vertex type as specified /// by the generic type parameter. /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public VertexBatch <T> GetBatch <T>() where T : struct, IVertexData { int typeIndex = VertexDeclaration.Get <T>().TypeIndex; if (typeIndex >= this.batches.Length) { return(null); } return(this.batches[typeIndex] as VertexBatch <T>); }
/// <summary> /// Returns the stored vertex batch for the specified batch index and vertex type. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="batchIndex"></param> /// <returns></returns> public VertexBatch <T> GetBatch <T>(int batchIndex) where T : struct, IVertexData { int typeIndex = VertexDeclaration.Get <T>().TypeIndex; if (typeIndex >= this.vertexDataSlots.Length) { return(null); } return((VertexBatch <T>) this.vertexDataSlots[typeIndex].Batches[batchIndex]); }
/// <summary> /// Returns the number of active vertex batches in storage for the specified /// vertex type. /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public int GetBatchCount <T>() where T : struct, IVertexData { int typeIndex = VertexDeclaration.Get <T>().TypeIndex; if (typeIndex >= this.vertexDataSlots.Length) { return(0); } return(this.vertexDataSlots[typeIndex].ActiveBatchCount); }
public override string ToString() { VertexDeclaration declaration = VertexDeclaration.Get(this.TypeIndex); return(string.Format( "{0}[{1}@{2}] as {3}, '{4}'", declaration.DataType.Name, this.Count, this.Offset, this.Mode, this.Material)); }
private RawList <T> AdvanceToNextBatch <T>() where T : struct, IVertexData { int typeIndex = VertexDeclaration.Get <T>().TypeIndex; int batchIndex = this.vertexDataSlots[typeIndex].ActiveBatchCount; List <IVertexBatch> batchList = this.vertexDataSlots[typeIndex].Batches; // Create a new batch, if we didn't already have one ready if (batchList.Count <= batchIndex) { batchList.Add(new VertexBatch <T>()); } // Assign current vertex batch for fast access VertexBatch <T> batch = (VertexBatch <T>)batchList[batchIndex]; this.vertexDataSlots[typeIndex].Vertices = batch.Vertices; this.vertexDataSlots[typeIndex].ActiveBatchCount++; return(batch.Vertices); }
private RawList <T> GetVertexList <T>() where T : struct, IVertexData { // Fast path: Retrieve and return int typeIndex = VertexDeclaration.Get <T>().TypeIndex; RawList <T> vertexList = null; if (typeIndex < this.vertices.Length && (vertexList = this.vertices[typeIndex] as RawList <T>) != null) { return(vertexList); } // Slow / init path else { if (typeIndex >= this.vertices.Length) { Array.Resize(ref this.batches, typeIndex + 1); Array.Resize(ref this.vertices, typeIndex + 1); } VertexBatch <T> batch = new VertexBatch <T>(); this.batches[typeIndex] = batch; this.vertices[typeIndex] = batch.Vertices; return(batch.Vertices); } }
/// <summary> /// Adds a parameterized set of vertices to the drawing devices rendering schedule. /// </summary> /// <typeparam name="T">The type of vertex data to add.</typeparam> /// <param name="material">The <see cref="Duality.Drawing.BatchInfo"/> to use for rendering the vertices.</param> /// <param name="vertexMode">The vertices drawing mode.</param> /// <param name="vertexBuffer"> /// A vertex data buffer that stores the vertices to add. Ownership of the buffer /// remains at the callsite, while the <see cref="IDrawDevice"/> copies the required /// data into internal storage. /// </param> /// <param name="vertexCount">The number of vertices to add, from the beginning of the buffer.</param> public void AddVertices <T>(BatchInfo material, VertexMode vertexMode, T[] vertexBuffer, int vertexOffset, int vertexCount) where T : struct, IVertexData { if (vertexCount == 0) { return; } if (vertexBuffer == null || vertexBuffer.Length == 0) { return; } if (vertexCount > vertexBuffer.Length) { vertexCount = vertexBuffer.Length; } if (material == null) { material = Material.SolidWhite.Res.Info; } // In picking mode, override incoming vertices material and vertex colors // to generate a lookup texture by which we can retrieve each pixels object. if (this.pickingIndex != 0) { ColorRgba clr = new ColorRgba((this.pickingIndex << 8) | 0xFF); for (int i = 0; i < vertexCount; ++i) { vertexBuffer[i].Color = clr; } material = this.RentMaterial(material); material.Technique = DrawTechnique.Picking; material.MainColor = ColorRgba.White; } else if (material.Technique == null || !material.Technique.IsAvailable) { material = this.RentMaterial(material); material.Technique = DrawTechnique.Solid; } // Move the added vertices to an internal shared buffer VertexSlice <T> slice = this.drawVertices.Rent <T>(vertexCount); Array.Copy(vertexBuffer, vertexOffset, slice.Data, slice.Offset, slice.Length); // Aggregate all info we have about our incoming vertices VertexDrawItem drawItem = new VertexDrawItem { Offset = (ushort)slice.Offset, Count = (ushort)slice.Length, BufferIndex = (byte)(this.drawVertices.GetBatchCount <T>() - 1), TypeIndex = (byte)VertexDeclaration.Get <T>().TypeIndex, Mode = vertexMode, Material = material }; // Determine whether we need depth sorting and calculate a reference depth bool sortByDepth = (this.projection == ProjectionMode.Screen) || material.Technique.Res.NeedsZSort; RawList <SortItem> sortBuffer = sortByDepth ? this.sortBufferBlended : this.sortBufferSolid; SortItem sortItem = new SortItem(); if (sortByDepth) { sortItem.SortDepth = this.CalcZSortIndex <T>(vertexBuffer, vertexOffset, vertexCount); } // Determine whether we can batch the new vertex item with the previous one int prevDrawIndex = -1; if (vertexMode.IsBatchableMode() && sortBuffer.Count > 0) { // Since we require a complete material match to append items, we can // assume that the previous items sortByDepth value is the same as ours. SortItem prevSortItem = sortBuffer.Data[sortBuffer.Count - 1]; // Compare the previously added item with the new one. If everything // except the vertices themselves is the same, we can append them directly. if (this.drawBuffer.Data[prevSortItem.DrawItemIndex].CanAppend(ref drawItem) && (!sortByDepth || sortItem.CanShareDepth(prevSortItem.SortDepth))) { prevDrawIndex = prevSortItem.DrawItemIndex; } } // Append the new item directly to the previous one, or add it as a new one if (prevDrawIndex != -1) { if (sortByDepth) { sortBuffer.Data[sortBuffer.Count - 1].MergeDepth( sortItem.SortDepth, this.drawBuffer.Data[prevDrawIndex].Count, drawItem.Count); } this.drawBuffer.Data[prevDrawIndex].Count += drawItem.Count; } else { sortItem.DrawItemIndex = this.drawBuffer.Count; sortBuffer.Add(sortItem); this.drawBuffer.Add(drawItem); } ++this.numRawBatches; }