#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 #ifndef NUCLEX_GRAPHICS_RASTERIZATION_VERTEXBUFFER_H #define NUCLEX_GRAPHICS_RASTERIZATION_VERTEXBUFFER_H #include "GenericVertexBuffer.h" #include namespace Nuclex { namespace Graphics { namespace Rasterization { // ------------------------------------------------------------------------------------------- // ///Stores strongly typed vertices used to define geometric features template class VertexBuffer : public GenericVertexBuffer { /// Initializes a vertex buffer with the specified capacity /// Number of vertices the vertex buffer will hold /// How the vertex buffer will be accessed public: VertexBuffer( std::size_t capacityInVertices, Usage::Enum usage = Usage::Immutable ) : GenericVertexBuffer(capacityInVertices * sizeof(TVertex), usage) {} /// Initializes a vertex buffer by copying an existing vertex buffer /// Vertex buffer that will be copied public: VertexBuffer(const VertexBuffer &other) : GenericVertexBuffer(other) {} /// Called when the vertex buffer is being destroyed public: virtual ~VertexBuffer() { OnDestroying(); } /// Retrieves the stride to get from one vertex to the next /// The stride of the vertex buffer in bytes public: virtual std::size_t GetStride() const { //TVertex *vertices = nullptr; //return reinterpret_cast(vertices[1]); return sizeof(TVertex); } /// Retrieves the total capacity of the vertex buffer in vertices /// The capacity of the vertex buffer in vertices public: std::size_t GetCapacityInVertices() const { return this->CapacityBytes / sizeof(TVertex); } /// Retrieves the number of vertices that have been used /// The number of used vertices in the vertex buffer public: std::size_t CountUsedVertices() const { return CountUsedBytes() / sizeof(TVertex); } /// Retrieves the number of elements a vertex consists of /// The number of elements in a vertex public: std::size_t CountVertexElements() const { return TDescriptor::Describe().size(); } /// Retrieves an array describing the elements a vertex consists of /// An array describing the elements a vertices are made up from public: virtual const VertexElement *GetVertexElements() const { return TDescriptor::Describe().data(); } /// Reads vertices from the vertex buffer /// Offset, in vertices, from which on data will be read /// Address at which the vertices read will be deposited /// Number of vertices that will be read public: void Read( std::size_t offset, TVertex *vertices, std::size_t count ) const { enforceRangeStaysWithinBuffer(offset, count); const TVertex *contentVertices = reinterpret_cast(this->Contents); count = std::min(count, CountUsedVertices() - offset); std::copy_n(contentVertices + offset, count, vertices); } /// Writes vertices into the vertex buffer /// Offset, in vertices, at which data will be written /// Vertices that will be written into the vertex buffer /// Number of vertices that will be written public: void Write( std::size_t offset, const TVertex *vertices, std::size_t count ) { std::size_t lastVertex = offset + count; if((offset >= this->CapacityBytes) || (lastVertex > this->CapacityBytes)) { throw std::out_of_range("Buffer write outside valid buffer range"); } TVertex *contentVertices = reinterpret_cast(this->Contents); std::copy_n(vertices, count, contentVertices + offset); OnChanged(offset * sizeof(TVertex), count * sizeof(TVertex)); } /// Appends the specified vertex to the end of the vertex buffer /// Vertex that will be appended /// The vertex buffer itself to allow for method chaining public: VertexBuffer &Append(const TVertex &vertex) { if(sizeof(TVertex) > this->CapacityBytes - CountUsedBytes()) { throw std::runtime_error("No more space in vertex buffer"); } Write(CountUsedVertices(), &vertex, 1); return *this; } /// Causes an exception if the specified range leaves the buffer /// Vertex at which the range starts /// Number of vertices that will be considered private: void enforceRangeStaysWithinBuffer( std::size_t firstVertex, std::size_t count ) const { std::size_t lastVertex = firstVertex + count; { std::size_t capacityInVertices = GetCapacityInVertices(); if((firstVertex >= capacityInVertices) || (lastVertex > capacityInVertices)) { throw std::out_of_range("Requested range leaves the vertex buffer"); } } #if _DEBUG { using namespace std; std::size_t usedVertexCount = CountUsedVertices(); assert( (firstVertex < usedVertexCount) && (lastVertex <= usedVertexCount) && "Vertex range should stay within the used area of the vertex buffer" ); } #endif } }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Graphics::Rasterization #endif // NUCLEX_GRAPHICS_RASTERIZATION_VERTEXBUFFER_H