/// <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; } }
/// <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); }
/// <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++; } } }