Пример #1
0
        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);
            }
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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);
        }
Пример #4
0
        /// <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>);
        }
Пример #5
0
        /// <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]);
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
            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));
            }
Пример #8
0
        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);
        }
Пример #9
0
        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);
            }
        }
Пример #10
0
        /// <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;
        }