Esempio n. 1
0
        /// <summary>
        /// Uploads the given index data to the internal index buffer. If the buffer is too
        /// small, a new one is created automatically.
        /// </summary>
        /// <param name="indexData">The IndexData instance to upload.</param>
        /// <param name="bufferUsage">The expected buffer usage. Use one of the constants defined in
        ///                    <code>BufferUsageARB</code>. Only used when the method call
        ///                    causes the creation of a new index buffer.</param>
        public void UploadIndexData(IndexData indexData, BufferUsage bufferUsage = BufferUsage.StaticDraw)
        {
            int  numIndices    = indexData.NumIndices;
            bool isQuadLayout  = indexData.UseQuadLayout;
            bool wasQuadLayout = IndexBufferUsesQuadLayout;

            if (IndexBufferName != 0)
            {
                if (numIndices <= IndexBufferSize)
                {
                    if (!isQuadLayout || !wasQuadLayout)
                    {
                        indexData.UploadToIndexBuffer(IndexBufferName, bufferUsage);
                        IndexBufferUsesQuadLayout = isQuadLayout && numIndices == IndexBufferSize;
                    }
                }
                else
                {
                    PurgeBuffers(false);
                }
            }
            if (IndexBufferName == 0)
            {
                IndexBufferName           = indexData.CreateIndexBuffer(true, bufferUsage);
                IndexBufferSize           = numIndices;
                IndexBufferUsesQuadLayout = isQuadLayout;
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Creates a duplicate of the IndexData object.
        /// </summary>
        public IndexData Clone()
        {
            var clone = new IndexData();

            clone._numIndices = _numIndices;
            if (!_useQuadLayout)
            {
                clone.SwitchToGenericData();
                Array.Copy(_rawData, clone._rawData, _rawData.Length);
            }
            return(clone);
        }
Esempio n. 3
0
        /// <summary>
        /// Copies the index data (or a range of it, defined by 'indexID' and 'numIndices')
        /// of this instance to another IndexData object, starting at a certain target index.
        /// If the target is not big enough, it will grow to fit all the new indices.
        ///
        /// <p>By passing a non-zero <code>offset</code>, you can raise all copied indices
        /// by that value in the target object.</p>
        /// </summary>
        public void CopyTo(IndexData target, int targetIndexId = 0, int offset = 0,
                           int indexId = 0, int numIndices = -1)
        {
            if (numIndices < 0 || indexId + numIndices > _numIndices)
            {
                numIndices = _numIndices - indexId;
            }

            short[] sourceData;
            int     newNumIndices = targetIndexId + numIndices;

            if (target._numIndices < newNumIndices)
            {
                target._numIndices = newNumIndices;
                if (_sQuadDataNumIndices < newNumIndices)
                {
                    EnsureQuadDataCapacity(newNumIndices);
                }
            }

            if (_useQuadLayout)
            {
                if (target._useQuadLayout)
                {
                    bool keepsQuadLayout = true;
                    int  distance        = targetIndexId - indexId;
                    int  distanceInQuads = distance / 6;
                    int  offsetInQuads   = offset / 4;

                    // This code is executed very often. If it turns out that both IndexData
                    // instances use a quad layout, we don't need to do anything here.
                    //
                    // When "distance / 6 == offset / 4 && distance % 6 == 0 && offset % 4 == 0",
                    // the copy operation preserves the quad layout. In that case, we can exit
                    // right away. The code below is a little more complex, though, to avoid the
                    // (surprisingly costly) mod-operations.
                    if (distanceInQuads == offsetInQuads && (offset & 3) == 0 &&
                        distanceInQuads * 6 == distance)
                    {
                        keepsQuadLayout = true;
                    }
                    else if (numIndices > 2)
                    {
                        keepsQuadLayout = false;
                    }
                    else
                    {
                        for (int i = 0; i < numIndices; ++i)
                        {
                            keepsQuadLayout = keepsQuadLayout &&
                                              (GetBasicQuadIndexAt(indexId + i) + offset == GetBasicQuadIndexAt(targetIndexId + i));
                        }
                    }

                    if (keepsQuadLayout)
                    {
                        return;
                    }
                    target.SwitchToGenericData();
                }

                sourceData = _sQuadData;

                if ((offset & 3) == 0) // => offset % 4 == 0
                {
                    indexId += 6 * offset / 4;
                    offset   = 0;
                    EnsureQuadDataCapacity(indexId + numIndices);
                }
            }
            else
            {
                if (target._useQuadLayout)
                {
                    target.SwitchToGenericData();
                }
                sourceData = _rawData;
            }

            if (target._rawData.Length < targetIndexId + numIndices)
            {
                Array.Resize(ref target._rawData, targetIndexId + numIndices);
            }
            if (offset == 0)
            {
                Array.Copy(sourceData, indexId, target._rawData, targetIndexId, numIndices);
            }
            else
            {
                int pos       = indexId;
                int targetPos = targetIndexId;
                for (int i = 0; i < numIndices; i++)
                {
                    target._rawData[targetPos] = (short)(sourceData[pos] + offset);
                    pos++;
                    targetPos++;
                }
            }
        }