//********************************** Banshee Engine (www.banshee3d.com) **************************************************// //**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************// #pragma once #include "BsCorePrerequisites.h" #include "BsGpuResourceData.h" #include "BsVertexBuffer.h" #include "BsIndexBuffer.h" #include "BsVertexDeclaration.h" #include "BsDrawOps.h" #include "BsSubMesh.h" #include "BsBounds.h" namespace BansheeEngine { /** @addtogroup Resources * @{ */ /** Iterator that allows you to easily populate or read vertex elements in MeshData. */ template class VertexElemIter { public: VertexElemIter() :mData(nullptr), mEnd(nullptr), mByteStride(0), mNumElements(0) { } VertexElemIter(UINT8* data, UINT32 byteStride, UINT32 numElements) :mData(data), mByteStride(byteStride), mNumElements(numElements) { mEnd = mData + byteStride * numElements; } /** Adds a new value to the iterators current position and advances the iterator. */ void addValue(const T& value) { setValue(value); moveNext(); } /** Sets a new value at the iterators current position. */ void setValue(const T& value) { memcpy(mData, &value, sizeof(T)); } /** Returns the value at the iterators current position. */ T& getValue() { return *((T*)mData); } /** Moves the iterator to the next position. Returns true if there are more elements. */ bool moveNext() { #ifdef BS_DEBUG_MODE if(mData >= mEnd) { BS_EXCEPT(InternalErrorException, "Vertex element iterator out of buffer bounds."); } #endif mData += mByteStride; return mData < mEnd; } /** Returns the number of elements this iterator can iterate over. */ UINT32 getNumElements() const { return mNumElements; } private: UINT8* mData; UINT8* mEnd; UINT32 mByteStride; UINT32 mNumElements; }; /** Contains per-vertex bone weights and indexes used for skinning, for up to four bones. */ struct BoneWeight { int index0; int index1; int index2; int index3; float weight0; float weight1; float weight2; float weight3; }; /** Contains mesh vertex and index data used for initializing, updating and reading mesh data from Mesh. */ class BS_CORE_EXPORT MeshData : public GpuResourceData { public: /** * Constructs a new object that can hold number of vertices described by the provided vertex data description. As * well as a number of indices of the provided type. */ MeshData(UINT32 numVertices, UINT32 numIndexes, const SPtr& vertexData, IndexType indexType = IT_32BIT); ~MeshData(); /** * Copies data from @p data parameter into the internal buffer for the specified semantic. * * @param[in] semantic Semantic that allows the engine to connect the data to a shader input slot. * @param[in] data Vertex data, containing at least @p size bytes. * @param[in] size The size of the data. Must be the size of the vertex element type * number of * vertices. * @param[in] semanticIdx (optional) If there are multiple semantics with the same name, use different index * to differentiate between them. * @param[in] streamIdx (optional) Zero-based index of the stream. Each stream will internally be * represented as a single vertex buffer. */ void setVertexData(VertexElementSemantic semantic, UINT8* data, UINT32 size, UINT32 semanticIdx = 0, UINT32 streamIdx = 0); /** * Copies data from the internal buffer to the pre-allocated buffer for the specified semantic. * * @param[in] semantic Semantic that allows the engine to connect the data to a shader input slot. * @param[in] data Buffer that will receive vertex data, of at least @p size bytes. * @param[in] size The size of the data. Must be the size of the vertex element type * number of * vertices. * @param[in] semanticIdx (optional) If there are multiple semantics with the same name, use different index * to differentiate between them. * @param[in] streamIdx (optional) Zero-based index of the stream. Each stream will internally be * represented as a single vertex buffer. */ void getVertexData(VertexElementSemantic semantic, UINT8* data, UINT32 size, UINT32 semanticIdx = 0, UINT32 streamIdx = 0); /** * Returns an iterator you can use for easily retrieving or setting Vector2 vertex elements. This is the preferred * method of assigning or reading vertex data. * * @note If vertex data of this type/semantic/index/stream doesn't exist and exception will be thrown. */ VertexElemIter getVec2DataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0); /** * Returns an iterator you can use for easily retrieving or setting Vector3 vertex elements. This is the preferred * method of assigning or reading vertex data. * * @note If vertex data of this type/semantic/index/stream doesn't exist and exception will be thrown. */ VertexElemIter getVec3DataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0); /** * Returns an iterator you can use for easily retrieving or setting Vector4 vertex elements. This is the preferred * method of assigning or reading vertex data. * * @note If vertex data of this type/semantic/index/stream doesn't exist and exception will be thrown. */ VertexElemIter getVec4DataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0); /** * Returns an iterator you can use for easily retrieving or setting DWORD vertex elements. This is the preferred * method of assigning or reading vertex data. * * @note If vertex data of this type/semantic/index/stream doesn't exist and exception will be thrown. */ VertexElemIter getDWORDDataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0); /** Returns the total number of vertices this object can hold. */ UINT32 getNumVertices() const { return mNumVertices; } /** Returns the total number of indices this object can hold. */ UINT32 getNumIndices() const; /** Returns a 16-bit pointer to the start of the internal index buffer. */ UINT16* getIndices16() const; /** Returns a 32-bit pointer to the start of the internal index buffer. */ UINT32* getIndices32() const; /** Returns the size of an index element in bytes. */ UINT32 getIndexElementSize() const; /** Returns the type of an index element. */ IndexType getIndexType() const { return mIndexType; } /** * Returns the pointer to the first element of the specified type. If you want to iterate over all elements you * need to call getVertexStride() to get the number of bytes you need to advance between each element. * * @param[in] semantic Semantic that allows the engine to connect the data to a shader input slot. * @param[in] semanticIdx (optional) If there are multiple semantics with the same name, use different index * to differentiate between them. * @param[in] streamIdx (optional) Zero-based index of the stream. Each stream will internally be * represented as a single vertex buffer. * @return null if it fails, else the element data. */ UINT8* getElementData(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const; /** * Returns an offset into the internal buffer where this element with the provided semantic starts. Offset is * provided in number of bytes. * * @param[in] semantic Semantic that allows the engine to connect the data to a shader input slot. * @param[in] semanticIdx (optional) If there are multiple semantics with the same name, use different index * to differentiate between them. * @param[in] streamIdx (optional) Zero-based index of the stream. Each stream will internally be * represented as a single vertex buffer. */ UINT32 getElementOffset(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const; /** Returns an object that describes data contained in a single vertex. */ const SPtr& getVertexDesc() const { return mVertexData; } /** Return the size (in bytes) of the entire buffer. */ UINT32 getSize() const { return getInternalBufferSize(); } /** Calculates the bounds of all vertices stored in the internal buffer. */ Bounds calculateBounds() const; /** * Combines a number of submeshes and their mesh data into one large mesh data buffer. * * @param[in] elements Data containing vertices and indices referenced by the submeshes. Number of elements * must be the same as number of submeshes. * @param[in] allSubMeshes Submeshes representing vertex and index range to take from mesh data and combine. * Number of submeshes must match the number of provided MeshData elements. * @param[out] subMeshes Outputs all combined sub-meshes with their new index and vertex offsets referencing * the newly created MeshData. * @return Combined mesh data containing all vertices and indexes references by the provided * sub-meshes. */ static SPtr combine(const Vector>& elements, const Vector>& allSubMeshes, Vector& subMeshes); /** * Constructs a new object that can hold number of vertices described by the provided vertex data description. As * well as a number of indices of the provided type. */ static SPtr create(UINT32 numVertices, UINT32 numIndexes, const SPtr& vertexData, IndexType indexType = IT_32BIT) { return bs_shared_ptr_new(numVertices, numIndexes, vertexData, indexType); } protected: /** Returns the size of the internal buffer in bytes. */ UINT32 getInternalBufferSize() const override; private: /** Returns a pointer to the start of the index buffer. */ UINT8* getIndexData() const { return getData(); } /** Returns a pointer to the start of the specified vertex stream. */ UINT8* getStreamData(UINT32 streamIdx) const; /** Returns an offset in bytes to the start of the index buffer from the start of the internal buffer. */ UINT32 getIndexBufferOffset() const; /** Returns an offset in bytes to the start of the stream from the start of the internal buffer. */ UINT32 getStreamOffset(UINT32 streamIdx = 0) const; /** Returns the size of the index buffer in bytes. */ UINT32 getIndexBufferSize() const; /** Returns the size of the specified stream in bytes. */ UINT32 getStreamSize(UINT32 streamIdx) const; /** Returns the size of all the streams in bytes. */ UINT32 getStreamSize() const; /** * Returns the data needed for iterating over the requested vertex element. * * @param[in] semantic Semantic of the element we are looking for. * @param[in] semanticIdx If there are multiple semantics with the same name, use different index to * differentiate between them. * @param[in] streamIdx Zero-based index of the stream the element resides in. * @param[out] data Pointer to the start of this elements data. * @param[out] stride Number of bytes between vertex elements of this type. */ void getDataForIterator(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx, UINT8*& data, UINT32& stride) const; private: friend class Mesh; friend class MeshCore; friend class MeshHeap; friend class MeshHeapCore; UINT32 mDescBuilding; UINT32 mNumVertices; UINT32 mNumIndices; IndexType mIndexType; SPtr mVertexData; /************************************************************************/ /* SERIALIZATION */ /************************************************************************/ private: MeshData(); // Serialization only public: friend class MeshDataRTTI; static RTTITypeBase* getRTTIStatic(); virtual RTTITypeBase* getRTTI() const override; }; /** @} */ }