#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2013 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License // If the library is compiled as a DLL, this ensures symbols are exported #define NUCLEX_GRAPHICS_SOURCE 1 #include "Nuclex/Graphics/Rasterization/IndexBuffer.h" #include #include #include #undef min namespace Nuclex { namespace Graphics { namespace Rasterization { // ------------------------------------------------------------------------------------------- // void IndexBuffer::Read( std::size_t offset, std::uint16_t *indices, std::size_t count ) const { enforceRangeStaysWithinBuffer(offset, count); const std::uint16_t *contents16 = reinterpret_cast( this->Contents ); count = std::min(count, CountUsedIndices() - offset); std::copy_n(contents16 + offset, count, indices); } // ------------------------------------------------------------------------------------------- // void IndexBuffer::Write( std::size_t offset, const std::uint16_t *indices, std::size_t count ) { std::size_t lastIndex = offset + count; if((offset >= this->CapacityBytes) || (lastIndex > this->CapacityBytes)) { throw std::out_of_range("Buffer write outside valid buffer range"); } std::uint16_t *contents16 = reinterpret_cast(this->Contents); std::copy_n(indices, count, contents16 + offset); OnChanged(offset * 2, count * 2); } // ------------------------------------------------------------------------------------------- // IndexBuffer::VertexRange IndexBuffer::GetLowestAndHighestVertexIndex( std::size_t firstIndex /* = 0 */, std::size_t count /* = static_cast(-1) */ ) const { if(count == static_cast(-1)) { std::size_t usedIndexCount = CountUsedIndices(); if(firstIndex >= usedIndexCount) { count = 0; } else { count = usedIndexCount - firstIndex; } } VertexRange range; if(count == 0) { range.first = 0; range.second = 0; } else { enforceRangeStaysWithinBuffer(firstIndex, count); const std::uint16_t *indices = reinterpret_cast( this->Contents ); range.first = indices[firstIndex]; range.second = range.first; ++firstIndex; std::size_t lastIndex = firstIndex + count; while(firstIndex < lastIndex) { std::uint16_t index = indices[firstIndex]; if(index < range.first) { range.first = index; } if(index > range.second) { range.second = index; } } ++range.second; } return range; } // ------------------------------------------------------------------------------------------- // void IndexBuffer::enforceRangeStaysWithinBuffer( std::size_t firstIndex, std::size_t count ) const { std::size_t lastIndex = firstIndex + count; { std::size_t capacityInIndices = GetCapacityInIndices(); if((firstIndex >= capacityInIndices) || (lastIndex > capacityInIndices)) { throw std::out_of_range("Requested range leaves the index buffer"); } } #if _DEBUG { std::size_t usedIndexCount = CountUsedIndices(); assert( (firstIndex < usedIndexCount) && (lastIndex <= usedIndexCount) && "Index range should stay within the used area of the index buffer" ); } #endif } // ------------------------------------------------------------------------------------------- // void IndexBuffer::Read( std::size_t offset, std::uint32_t *indices, std::size_t count ) const { enforceRangeStaysWithinBuffer(offset, count); const std::uint32_t *contents32 = reinterpret_cast( this->Contents ); count = std::min(count, CountUsedIndices() - offset); std::copy_n(contents32 + offset, count, indices); } // ------------------------------------------------------------------------------------------- // void IndexBuffer::Write( std::size_t offset, const std::uint32_t *indices, std::size_t count ) { std::size_t lastIndex = offset + count; if((offset >= this->CapacityBytes) || (lastIndex > this->CapacityBytes)) { throw std::out_of_range("Buffer write outside valid buffer range"); } std::uint32_t *contents32 = reinterpret_cast(this->Contents); std::copy_n(indices, count, contents32 + offset); OnChanged(offset * 4, count * 4); } // ------------------------------------------------------------------------------------------- // IndexBuffer::VertexRange IndexBuffer::GetLowestAndHighestVertexIndex( std::size_t firstIndex /* = 0 */, std::size_t count /* = static_cast(-1) */ ) const { if(count == static_cast(-1)) { std::size_t usedIndexCount = CountUsedIndices(); if(firstIndex >= usedIndexCount) { count = 0; } else { count = usedIndexCount - firstIndex; } } VertexRange range; if(count == 0) { range.first = 0; range.second = 0; } else { enforceRangeStaysWithinBuffer(firstIndex, count); const std::uint32_t *indices = reinterpret_cast( this->Contents ); range.first = indices[firstIndex]; range.second = range.first; ++firstIndex; std::size_t lastIndex = firstIndex + count; while(firstIndex < lastIndex) { std::uint32_t index = indices[firstIndex]; if(index < range.first) { range.first = index; } if(index > range.second) { range.second = index; } } ++range.second; } return range; } // ------------------------------------------------------------------------------------------- // void IndexBuffer::enforceRangeStaysWithinBuffer( std::size_t firstIndex, std::size_t count ) const { std::size_t lastIndex = firstIndex + count; { std::size_t capacityInIndices = GetCapacityInIndices(); if((firstIndex >= capacityInIndices) || (lastIndex > capacityInIndices)) { throw std::out_of_range("Requested range leaves the index buffer"); } } #if _DEBUG { using namespace std; std::size_t usedIndexCount = CountUsedIndices(); assert( (firstIndex < usedIndexCount) && (lastIndex <= usedIndexCount) && "Index range should stay within the used area of the index buffer" ); } #endif } // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Graphics::Rasterization