#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_SCENE_MESHES_MESH_H #define NUCLEX_SCENE_MESHES_MESH_H #include "Nuclex/Scene/Config.h" #include "Nuclex/Scene/Position3.h" #include #include #include namespace Nuclex { namespace Scene { namespace Meshes { // ------------------------------------------------------------------------------------------- // /// Mesh built from 3D vertices forming a triangle topology /// /// This class stores any number of arbitrary data streams in a non-interleaved format. /// It is intended for interfacing with model importers and to feed (usually interleaved) /// vertex buffers with the elements the shader actually processes. /// class Mesh { #pragma region class GenericVertexContainer /// Generic interface to a vertex data stream private: class GenericVertexContainer { /// Frees all resources used by the vertex data stream public: virtual ~GenericVertexContainer() {} /// Retrieves the size of a vertex element of this type /// The size of a single vertex element of this type public: virtual std::size_t GetElementSize() const = 0; /// Accesses the contents of the vertex data stream /// A pointer to the beginning of the vertex data stream public: virtual void *Access() = 0; /// Creates a copy of the vertex data stream /// The size of the vertex data stream being cloned /// A copy of the vertex data stream public: virtual GenericVertexContainer *Clone(std::size_t count) const = 0; }; #pragma endregion // class GenericVertexContainer #pragma region class VertexContainer /// Stores the contents of a vertex data stream private: template class VertexContainer : public GenericVertexContainer { /// Initializes a new vertex data stream /// Number of vertices in the vertex data stream public: VertexContainer(std::size_t count) : data(new TVertexData[count]) {} /// Frees all resources used by the vertex data stream public: virtual ~VertexContainer() {} /// Retrieves the size of a vertex element of this type /// The size of a single vertex element of this type public: virtual std::size_t GetElementSize() const { // Alignment rules: elements in an array are always contiguous. If alignment // is performed, it is performed within the structure, so a sizeof on // a single element is guaranteed to be identical to the array's stride. return sizeof(TVertexData); } /// Accesses the contents of the vertex data stream /// A pointer to the beginning of the vertex data stream public: void *Access() { return static_cast(this->data.get()); } /// Creates a copy of the vertex data stream /// The size of the vertex data stream being cloned /// A copy of the vertex data stream public: VertexContainer *Clone(std::size_t count) const { std::unique_ptr clone(new VertexContainer(count)); std::copy_n(this->data.get(), count, clone->data.get()); return clone.release(); } /// Contents of the vertex data stream private: std::unique_ptr data; }; #pragma endregion // class VertexContainer /// Initializes a new mesh /// Number of vertices the mesh will store /// Number of indices used by the mesh public: Mesh(std::size_t vertexCount, std::size_t indexCount) : indexCount(indexCount), indices(new std::uint16_t[indexCount]), vertexCount(vertexCount) {} /// Counts the number of vertices in the model public: std::size_t CountVertices() const { return this->vertexCount; } /// Counts the number of indices used to build polygons from the vertices public: std::size_t CountIndices() const { return this->indexCount; } /// Checks whether vertex data of the specified type is present /// Type of vertex data that will be checked for /// True if vertex data of the specified type is present public: template bool HasVertexData() const { return HasVertexData(typeid(TVertexData)); } /// Checks whether vertex data of the specified type is present /// Type id of the vertex data stream that will be retrieved /// True if vertex data of the specified type is present public: bool HasVertexData(std::uint32_t type) const { for(std::size_t index = 0; index < this->vertexData.size(); ++index) { if(type == this->vertexData[index].first) { return true; } } return false; } /// Accesses the vertex data of the specified type /// Which type of vertex data will be accessed /// Type id of the vertex data stream that will be retrieved /// Whether to create the data stream if it doesn't exist /// /// /// Meshes store vertex data of any arbitrary type. Normally each vertex has at least /// a set of 3D coordinates () describing its location and /// texture coordinates () to indicate which point of /// the texture should match up with the corner of the triangle the vertex represents. /// /// /// The type ids of these any other standard vertex data streams can be found /// in the VertexElementIds header. /// /// public: template TVertexData *AccessVertexData( std::uint32_t type, bool create = false ) { for(std::size_t index = 0; index < this->vertexData.size(); ++index) { if(type == this->vertexData[index].first) { return static_cast(this->vertexData[index].second->Access()); } } if(create) { std::unique_ptr> vertexContainer( new VertexContainer(this->vertexCount) ); TVertexData *data = static_cast(vertexContainer->Access()); this->vertexData.push_back(std::make_pair(type, std::move(vertexContainer))); return data; } else { throw std::exception("Mesh does not contain a stream of specified vertex data type"); } } /// Accesses the vertex data of the specified type /// Which type of vertex data will be accessed /// Type id of the vertex data stream that will be retrieved /// /// Meshes store vertex data of any arbitrary type. Typically each vertex has at least /// a set of 3D coordinates () describing its location and /// texture coordinates () to indicate which point of the texture /// should match up with the corner of the triangle the vertex represents. /// public: template const TVertexData *AccessVertexData( std::uint32_t type ) const { const std::type_info type = typeid(TVertexData); for(std::size_t index = 0; index < this->vertexData.size(); ++index) { if(type == this->vertexData[index].first) { return static_cast(this->vertexData[index].second->Access()); } } throw std::exception("Mesh does not contain a stream of the specified vertex data type"); } /// Accessess the indices used to connect vertices to triangles public: std::uint16_t *AccessIndices() { return this->indices.get(); } /// Accessess the indices used to connect vertices to triangles public: const std::uint16_t *AccessIndices() const { return this->indices.get(); } /// Pointer to a vertex data container private: typedef std::unique_ptr VertexContainerPointer; /// Pairs the type of vertex data stroed with the vertex data container private: typedef std::pair TypeVertexPair; /// Vertex data streams the mesh is equipped with private: typedef std::vector VertexDataVector; /// Number of indices used by the mesh private: std::size_t indexCount; /// Indices establishing how the vertices connect to a triangle topology private: std::unique_ptr indices; /// Number of vertices used by the mesh private: std::size_t vertexCount; /// Stores the data attached to each of the mesh's vertices private: VertexDataVector vertexData; }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Scene::Meshes #endif // NUCLEX_SCENE_MESHES_MESH_H