| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- #include "CmMeshData.h"
- #include "CmVector2.h"
- #include "CmVector3.h"
- #include "CmHardwareBufferManager.h"
- #include "CmMeshDataRTTI.h"
- #include "CmVertexDeclaration.h"
- #include "CmException.h"
- namespace CamelotEngine
- {
- MeshData::MeshData(IndexBuffer::IndexType indexType)
- :mIndexType(indexType)
- {
- }
- MeshData::~MeshData()
- {
- for(auto& vertElems : mVertexData)
- {
- for(auto& vertElem : vertElems.second)
- {
- if(vertElem.data != nullptr)
- CM_DELETE_BYTES(vertElem.data, ScratchAlloc);
- }
- }
- for(auto& indexData : mIndices)
- {
- if(indexData.indices != nullptr)
- CM_DELETE_BYTES(indexData.indices, ScratchAlloc);
- }
- }
- Vector2* MeshData::addPositionsVec2(UINT32 numElements, UINT32 streamIdx)
- {
- return reinterpret_cast<Vector2*>(addVertexElementData(VET_FLOAT2, VES_POSITION, numElements, 0, streamIdx));
- }
- Vector3* MeshData::addPositionsVec3(UINT32 numElements, UINT32 streamIdx)
- {
- return reinterpret_cast<Vector3*>(addVertexElementData(VET_FLOAT3, VES_POSITION, numElements, 0, streamIdx));
- }
- Vector4* MeshData::addPositionsVec4(UINT32 numElements, UINT32 streamIdx)
- {
- return reinterpret_cast<Vector4*>(addVertexElementData(VET_FLOAT4, VES_POSITION, numElements, 0, streamIdx));
- }
- Vector3* MeshData::addNormals(UINT32 numElements, UINT32 streamIdx)
- {
- return reinterpret_cast<Vector3*>(addVertexElementData(VET_FLOAT3, VES_NORMAL, numElements, 0, streamIdx));
- }
- Vector3* MeshData::addTangentsVec3(UINT32 numElements, UINT32 streamIdx)
- {
- return reinterpret_cast<Vector3*>(addVertexElementData(VET_FLOAT3, VES_TANGENT, numElements, 0, streamIdx));
- }
- Vector4* MeshData::addTangentsVec4(UINT32 numElements, UINT32 streamIdx)
- {
- return reinterpret_cast<Vector4*>(addVertexElementData(VET_FLOAT4, VES_TANGENT, numElements, 0, streamIdx));
- }
- Vector3* MeshData::addBitangents(UINT32 numElements, UINT32 streamIdx)
- {
- return reinterpret_cast<Vector3*>(addVertexElementData(VET_FLOAT3, VES_BITANGENT, numElements, 0, streamIdx));
- }
- Vector2* MeshData::addUV0(UINT32 numElements, UINT32 streamIdx)
- {
- return reinterpret_cast<Vector2*>(addVertexElementData(VET_FLOAT2, VES_TEXCOORD, numElements, 0, streamIdx));
- }
- Vector2* MeshData::addUV1(UINT32 numElements, UINT32 streamIdx)
- {
- return reinterpret_cast<Vector2*>(addVertexElementData(VET_FLOAT2, VES_TEXCOORD, numElements, 1, streamIdx));
- }
- Color* MeshData::addColorsFloat(UINT32 numElements, UINT32 streamIdx)
- {
- return reinterpret_cast<Color*>(addVertexElementData(VET_FLOAT4, VES_COLOR, numElements, 0, streamIdx));
- }
- UINT32* MeshData::addColorsDWORD(UINT32 numElements, UINT32 streamIdx)
- {
- return reinterpret_cast<UINT32*>(addVertexElementData(VET_COLOR, VES_COLOR, numElements, 0, streamIdx));
- }
- UINT8* MeshData::addVertexElementData(VertexElementType type, VertexElementSemantic semantic, UINT32 numElements, UINT32 semanticIdx, UINT32 streamIdx)
- {
- clearIfItExists(type, semantic, semanticIdx, streamIdx);
- UINT32 elemSize = VertexElement::getTypeSize(type);
- UINT8* elements = CM_NEW_BYTES(elemSize * numElements, ScratchAlloc);
- vector<VertexElementData>::type& elemData = mVertexData[streamIdx];
- VertexElementData newElement(type, semantic, semanticIdx, streamIdx, elements, numElements);
- elemData.push_back(newElement);
- return elements;
- }
- UINT32* MeshData::addIndices32(UINT32 numIndices, UINT32 subMesh)
- {
- if(mIndexType != IndexBuffer::IT_32BIT)
- CM_EXCEPT(InvalidParametersException, "Trying to set 32bit indices but the MeshData was initialized as 16bit.");
- if(subMesh >= mIndices.size())
- mIndices.resize(subMesh + 1);
- IndexElementData indexData = mIndices[subMesh];
- if(indexData.indices != nullptr)
- CM_DELETE_BYTES(indexData.indices, ScratchAlloc);
- UINT32* indices = (UINT32*)CM_NEW_BYTES(numIndices * sizeof(UINT32), ScratchAlloc);
- indexData.indices = (UINT8*)indices;
- indexData.numIndices = numIndices;
- indexData.elementSize = getIndexElementSize();
- indexData.subMesh = subMesh;
- mIndices[subMesh] = indexData;
- return indices;
- }
- UINT16* MeshData::addIndices16(UINT32 numIndices, UINT32 subMesh)
- {
- if(mIndexType != IndexBuffer::IT_16BIT)
- CM_EXCEPT(InvalidParametersException, "Trying to set 16bit indices but the MeshData was initialized as 32bit.");
- if(subMesh >= mIndices.size())
- mIndices.resize(subMesh + 1);
- IndexElementData indexData = mIndices[subMesh];
- if(indexData.indices != nullptr)
- CM_DELETE_BYTES(indexData.indices, ScratchAlloc);
- UINT16* indices = (UINT16*)CM_NEW_BYTES(numIndices * sizeof(UINT16), ScratchAlloc);
- indexData.indices = (UINT8*)indices;
- indexData.numIndices = numIndices;
- indexData.elementSize = getIndexElementSize();
- indexData.subMesh = subMesh;
- mIndices[subMesh] = indexData;
- return indices;
- }
- VertexDeclarationPtr MeshData::createDeclaration() const
- {
- VertexDeclarationPtr declaration = HardwareBufferManager::instance().createVertexDeclaration();
- for(auto& vertElems : mVertexData)
- {
- UINT32 offset = 0;
- for(auto& vertElem : vertElems.second)
- {
- declaration->addElement(vertElems.first, offset, vertElem.element.getType(), vertElem.element.getSemantic(), vertElem.element.getIndex());
- offset += vertElem.element.getSize();
- }
- }
- return declaration;
- }
- UINT32 MeshData::getNumVertices() const
- {
- UINT32 numVertices = 0;
- auto vertElemDataPerStream = mVertexData;
- MeshData::VertexElementData* firstElemData = nullptr;
- if(vertElemDataPerStream.size() > 0)
- {
- auto vertElemData = vertElemDataPerStream.begin()->second;
- auto firstVertElem = vertElemData.begin();
- if(firstVertElem != vertElemData.end())
- {
- numVertices = firstVertElem->elementCount;
- }
- }
- for(auto& vertElems : mVertexData)
- {
- for(auto& vertElem : vertElems.second)
- {
- if(vertElem.elementCount != numVertices)
- {
- CM_EXCEPT(InvalidParametersException, "All vertex element arrays in MeshData need to be of the same size. Found an array with semantic: " \
- + toString(vertElem.element.getSemantic()) + " and element count: " + toString(vertElem.elementCount) + ". This doesn't match with other " \
- + "element with semantic: " + toString(firstElemData->element.getSemantic()) + " and element count: " + toString(firstElemData->elementCount));
- }
- }
- }
- return numVertices;
- }
- UINT32 MeshData::getNumIndices(UINT32 subMesh) const
- {
- return mIndices.at(subMesh).numIndices;
- }
- UINT16* MeshData::getIndices16(UINT32 subMesh) const
- {
- return (UINT16*)mIndices.at(subMesh).indices;
- }
- UINT32* MeshData::getIndices32(UINT32 subMesh) const
- {
- return (UINT32*)mIndices.at(subMesh).indices;
- }
- vector<VertexElement>::type MeshData::getVertexElements() const
- {
- vector<VertexElement>::type elements;
- for(auto& vertElems : mVertexData)
- {
- UINT32 offset = 0;
- for(auto& vertElem : vertElems.second)
- {
- elements.push_back(vertElem.element);
- }
- }
- return elements;
- }
- MeshDataPtr MeshData::combine(const vector<MeshDataPtr>::type& elements)
- {
- MeshDataPtr combinedMeshData(CM_NEW(MeshData, PoolAlloc) MeshData(),
- &MemAllocDeleter<MeshData, PoolAlloc>::deleter);
- UINT32 subMeshIndex = 0;
- vector<VertexElement>::type combinedVertexElements;
- vector<UINT8*>::type vertexElemData;
- vector<UINT32>::type bufferOffsets;
- UINT32 totalVertexCount = 0;
- UINT32 vertexIndexOffset = 0;
- for(auto& meshData : elements)
- {
- for(UINT32 i = 0; i < meshData->getNumSubmeshes(); i++)
- {
- UINT32 numIndices = meshData->getNumIndices(i);
- UINT32* indices = combinedMeshData->addIndices32(numIndices, subMeshIndex);
- UINT32* sourceIndices = meshData->getIndices32(i);
- for(UINT32 j = 0; j < numIndices; j++)
- indices[j] = sourceIndices[j] + vertexIndexOffset;
- subMeshIndex++;
- }
- UINT32 numVertices = meshData->getNumVertices();
- totalVertexCount += numVertices;
- vertexIndexOffset += numVertices;
- }
- UINT32 vertexOffset = 0;
- for(auto& meshData : elements)
- {
- vector<VertexElement>::type vertexElements = meshData->getVertexElements();
- UINT32 numVertices = meshData->getNumVertices();
- for(auto& newElement : vertexElements)
- {
- INT32 alreadyExistsIdx = -1;
- UINT32 idx = 0;
- for(auto& existingElement : combinedVertexElements)
- {
- if(newElement == existingElement)
- {
- alreadyExistsIdx = idx;
- break;
- }
- idx++;
- }
- if(alreadyExistsIdx == -1)
- {
- combinedVertexElements.push_back(newElement);
-
- UINT8* newBuffer = combinedMeshData->addVertexElementData(newElement.getType(), newElement.getSemantic(), totalVertexCount, newElement.getIndex(), newElement.getSource());
-
- UINT32 newBufferSize = totalVertexCount * newElement.getSize();
- memset(newBuffer, 0, newBufferSize);
- vertexElemData.push_back(newBuffer);
- bufferOffsets.push_back(0);
- alreadyExistsIdx = (UINT32)vertexElemData.size() - 1;
- }
- UINT8* source = meshData->getVertElemData(newElement.getType(), newElement.getSemantic(), newElement.getIndex(), newElement.getSource()).data;
- UINT32 offset = vertexOffset * newElement.getSize();
- memcpy(&(vertexElemData[alreadyExistsIdx]) + offset, source, numVertices * newElement.getSize());
- }
- vertexOffset += meshData->getNumVertices();
- }
- return combinedMeshData;
- }
- bool MeshData::hasElement(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
- {
- auto elemDataIter = mVertexData.find(streamIdx);
- if(elemDataIter == mVertexData.end())
- return false;
- const vector<VertexElementData>::type& elemData = elemDataIter->second;
- auto findIter = std::find_if(elemData.begin(), elemData.end(),
- [semantic, semanticIdx] (const VertexElementData& x)
- {
- return x.element.getSemantic() == semantic && x.element.getIndex() == semanticIdx;
- });
- if(findIter != elemData.end())
- return true;
- return false;
- }
- void MeshData::clearIfItExists(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx)
- {
- vector<VertexElementData>::type& elemData = mVertexData[streamIdx];
- auto findIter = std::find_if(elemData.begin(), elemData.end(),
- [type, semantic, semanticIdx] (const VertexElementData& x)
- {
- return x.element.getSemantic() == semantic && x.element.getIndex() == semanticIdx;
- });
- if(findIter != elemData.end())
- {
- if(findIter->data != nullptr)
- CM_DELETE_BYTES(findIter->data, ScratchAlloc);
- elemData.erase(findIter);
- }
- }
- MeshData::VertexElementData& MeshData::getVertElemData(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx)
- {
- vector<VertexElementData>::type& elemData = mVertexData[streamIdx];
- auto findIter = std::find_if(elemData.begin(), elemData.end(),
- [type, semantic, semanticIdx] (const VertexElementData& x)
- {
- return x.element.getSemantic() == semantic && x.element.getIndex() == semanticIdx;
- });
- if(findIter == elemData.end())
- CM_EXCEPT(InvalidParametersException, "No vertex element of specified type exists.");
- return *findIter;
- }
- /************************************************************************/
- /* SERIALIZATION */
- /************************************************************************/
- RTTITypeBase* MeshData::VertexElementData::getRTTIStatic()
- {
- return VertexElementDataRTTI::instance();
- }
- RTTITypeBase* MeshData::VertexElementData::getRTTI() const
- {
- return VertexElementData::getRTTIStatic();
- }
- RTTITypeBase* MeshData::IndexElementData::getRTTIStatic()
- {
- return IndexElementDataRTTI::instance();
- }
- RTTITypeBase* MeshData::IndexElementData::getRTTI() const
- {
- return IndexElementData::getRTTIStatic();
- }
- RTTITypeBase* MeshData::getRTTIStatic()
- {
- return MeshDataRTTI::instance();
- }
- RTTITypeBase* MeshData::getRTTI() const
- {
- return MeshData::getRTTIStatic();
- }
- }
|