shared_ptr <MeshAttributeVector> GLTFMesh::meshAttributes() { shared_ptr <MeshAttributeVector> meshAttributes(new MeshAttributeVector()); vector <GLTF::Semantic> allSemantics = this->allSemantics(); std::map<string, unsigned int> semanticAndSetToIndex; for (unsigned int i = 0 ; i < allSemantics.size() ; i++) { GLTF::Semantic semantic = allSemantics[i]; size_t attributesCount = this->getMeshAttributesCountForSemantic(semantic); for (size_t j = 0 ; j < attributesCount ; j++) { shared_ptr <GLTF::GLTFAccessor> selectedMeshAttribute = this->getMeshAttribute(semantic, j); unsigned int indexSet = j; std::string semanticIndexSetKey = keyWithSemanticAndSet(semantic, indexSet); unsigned int size = (unsigned int)meshAttributes->size(); semanticAndSetToIndex[semanticIndexSetKey] = size; meshAttributes->push_back(selectedMeshAttribute); } } return meshAttributes; }
shared_ptr <MeshAttributeVector> GLTFMesh::meshAttributes() { shared_ptr <MeshAttributeVector> meshAttributes(new MeshAttributeVector()); vector <GLTF::Semantic> allSemantics = this->allSemantics(); std::map<string, unsigned int> semanticAndSetToIndex; for (unsigned int i = 0 ; i < allSemantics.size() ; i++) { IndexSetToMeshAttributeHashmap& indexSetToMeshAttribute = this->getMeshAttributesForSemantic(allSemantics[i]); IndexSetToMeshAttributeHashmap::const_iterator meshAttributeIterator; for (meshAttributeIterator = indexSetToMeshAttribute.begin() ; meshAttributeIterator != indexSetToMeshAttribute.end() ; meshAttributeIterator++) { //(*it).first; // the key value (of type Key) //(*it).second; // the mapped value (of type T) shared_ptr <GLTF::GLTFMeshAttribute> selectedMeshAttribute = (*meshAttributeIterator).second; unsigned int indexSet = (*meshAttributeIterator).first; GLTF::Semantic semantic = allSemantics[i]; std::string semanticIndexSetKey = keyWithSemanticAndSet(semantic, indexSet); unsigned int size = (unsigned int)meshAttributes->size(); semanticAndSetToIndex[semanticIndexSetKey] = size; meshAttributes->push_back(selectedMeshAttribute); } } return meshAttributes; }
bool JSONMesh::buildUniqueIndexes() { unsigned int startIndex = 1; // begin at 1 because the hashtable will return 0 when the element is not present unsigned int endIndex = 0; unsigned int primitiveCount = (unsigned int)_primitives.size(); unsigned int maxVertexAttributes = 0; if (primitiveCount == 0) { // FIXME: report error return false; } //in _allOriginalAccessors we'll get the flattened list of all the accessors as a vector. //fill semanticAndSetToIndex with key: (semantic, indexSet) value: index in _allOriginalAccessors vector. _allOriginalAccessors.clear(); vector <JSONExport::Semantic> allSemantics = this->allSemantics(); std::map<string, unsigned int> semanticAndSetToIndex; for (unsigned int i = 0 ; i < allSemantics.size() ; i++) { IndexSetToAccessorHashmap& indexSetToAccessor = this->getAccessorsForSemantic(allSemantics[i]); IndexSetToAccessorHashmap::const_iterator accessorIterator; for (accessorIterator = indexSetToAccessor.begin() ; accessorIterator != indexSetToAccessor.end() ; accessorIterator++) { //(*it).first; // the key value (of type Key) //(*it).second; // the mapped value (of type T) shared_ptr <JSONExport::JSONAccessor> selectedAccessor = (*accessorIterator).second; unsigned int indexSet = (*accessorIterator).first; JSONExport::Semantic semantic = allSemantics[i]; std::string semanticIndexSetKey = keyWithSemanticAndSet(semantic, indexSet); unsigned int size = _allOriginalAccessors.size(); semanticAndSetToIndex[semanticIndexSetKey] = size; //printf("set %d for key: %s\n",size, semanticIndexSetKey.c_str()); _allOriginalAccessors.push_back(selectedAccessor); } } maxVertexAttributes = _allOriginalAccessors.size(); vector <shared_ptr<JSONExport::JSONPrimitiveRemapInfos> > allPrimitiveRemapInfos; if (primitiveCount > 0) { //build a array that maps the accessors that the indices points to with the index of the indice. JSONExport::RemappedMeshIndexesHashmap remappedMeshIndexesMap; for (unsigned int i = 0 ; i < primitiveCount ; i++) { std::vector< shared_ptr<JSONExport::JSONIndices> > allIndices = this->_primitives[i]->allIndices(); unsigned int* indicesInRemapping = (unsigned int*)malloc(sizeof(unsigned int) * allIndices.size()); for (unsigned int k = 0 ; k < allIndices.size() ; k++) { JSONExport::Semantic semantic = allIndices[k]->getSemantic(); unsigned int indexSet = allIndices[k]->getIndexOfSet(); std::string semanticIndexSetKey = keyWithSemanticAndSet(semantic, indexSet); unsigned int idx = semanticAndSetToIndex[semanticIndexSetKey]; //printf("git %d for key: %s\n",idx, semanticIndexSetKey.c_str()); indicesInRemapping[k] = idx; } shared_ptr<JSONExport::JSONPrimitiveRemapInfos> primitiveRemapInfos = this->_primitives[i]->buildUniqueIndexes(remappedMeshIndexesMap, indicesInRemapping, startIndex, endIndex); free(indicesInRemapping); if (primitiveRemapInfos.get()) { startIndex = endIndex; allPrimitiveRemapInfos.push_back(primitiveRemapInfos); } else { // FIXME: report error return false; } } } else { return false; } // we are using WebGL for rendering, this involve OpenGL/ES where only float are supported. // now we got not only the uniqueIndexes but also the number of different indexes, i.e the number of vertex attributes count // we can allocate the buffer to hold vertex attributes unsigned int vertexCount = endIndex - 1; for (unsigned int i = 0 ; i < allSemantics.size() ; i++) { IndexSetToAccessorHashmap& indexSetToAccessor = this->getAccessorsForSemantic(allSemantics[i]); IndexSetToAccessorHashmap::const_iterator accessorIterator; //FIXME: consider turn this search into a method for mesh for (accessorIterator = indexSetToAccessor.begin() ; accessorIterator != indexSetToAccessor.end() ; accessorIterator++) { //(*it).first; // the key value (of type Key) //(*it).second; // the mapped value (of type T) shared_ptr <JSONExport::JSONAccessor> selectedAccessor = (*accessorIterator).second; size_t sourceSize = vertexCount * selectedAccessor->getElementByteLength(); void* sourceData = malloc(sourceSize); shared_ptr <JSONExport::JSONBuffer> referenceBuffer = selectedAccessor->getBuffer(); shared_ptr <JSONExport::JSONDataBuffer> remappedBuffer(new JSONExport::JSONDataBuffer(referenceBuffer->getID(), sourceData, sourceSize, true)); shared_ptr <JSONExport::JSONAccessor> remappedAccessor(new JSONExport::JSONAccessor(selectedAccessor.get())); remappedAccessor->setBuffer(remappedBuffer); remappedAccessor->setCount(vertexCount); indexSetToAccessor[(*accessorIterator).first] = remappedAccessor; _allRemappedAccessors.push_back(remappedAccessor); } } /* if (_allOriginalAccessors.size() != allIndices.size()) { // FIXME: report error return false; } */ for (unsigned int i = 0 ; i < primitiveCount ; i++) { if (!_primitives[i]->_remapVertexes(this->_allOriginalAccessors , this->_allRemappedAccessors, allPrimitiveRemapInfos[i])) { // FIXME: report error return false; } } if (endIndex > 65535) { //The mesh should be split but we do not handle this feature yet printf("WARNING: mesh has more than 65535 vertex, splitting has to be done for GL/ES \n"); return false; //for now return false as splitting is not implemented } return true; }
shared_ptr <GLTFMesh> createUnifiedIndexesMeshFromMesh(GLTFMesh *sourceMesh, std::vector< shared_ptr<IndicesVector> > &vectorOfIndicesVector) { MeshAttributeVector originalMeshAttributes; MeshAttributeVector remappedMeshAttributes; shared_ptr <GLTFMesh> targetMesh(new GLTFMesh(*sourceMesh)); PrimitiveVector sourcePrimitives = sourceMesh->getPrimitives(); PrimitiveVector targetPrimitives = targetMesh->getPrimitives(); size_t startIndex = 0; size_t endIndex = 0; size_t primitiveCount = sourcePrimitives.size(); unsigned int maxVertexAttributes = 0; if (primitiveCount == 0) { // FIXME: report error //return 0; } //in originalMeshAttributes we'll get the flattened list of all the meshAttributes as a vector. //fill semanticAndSetToIndex with key: (semantic, indexSet) value: index in originalMeshAttributes vector. vector <GLTF::Semantic> allSemantics = sourceMesh->allSemantics(); std::map<string, unsigned int> semanticAndSetToIndex; for (unsigned int i = 0 ; i < allSemantics.size() ; i++) { IndexSetToMeshAttributeHashmap& indexSetToMeshAttribute = sourceMesh->getMeshAttributesForSemantic(allSemantics[i]); IndexSetToMeshAttributeHashmap::const_iterator meshAttributeIterator; for (meshAttributeIterator = indexSetToMeshAttribute.begin() ; meshAttributeIterator != indexSetToMeshAttribute.end() ; meshAttributeIterator++) { //(*it).first; // the key value (of type Key) //(*it).second; // the mapped value (of type T) shared_ptr <GLTF::GLTFMeshAttribute> selectedMeshAttribute = (*meshAttributeIterator).second; unsigned int indexSet = (*meshAttributeIterator).first; GLTF::Semantic semantic = allSemantics[i]; std::string semanticIndexSetKey = keyWithSemanticAndSet(semantic, indexSet); unsigned int size = (unsigned int)originalMeshAttributes.size(); semanticAndSetToIndex[semanticIndexSetKey] = size; originalMeshAttributes.push_back(selectedMeshAttribute); } } maxVertexAttributes = (unsigned int)originalMeshAttributes.size(); vector <shared_ptr<GLTF::GLTFPrimitiveRemapInfos> > allPrimitiveRemapInfos; //build a array that maps the meshAttributes that the indices points to with the index of the indice. GLTF::RemappedMeshIndexesHashmap remappedMeshIndexesMap; for (unsigned int i = 0 ; i < primitiveCount ; i++) { shared_ptr<IndicesVector> allIndicesSharedPtr = vectorOfIndicesVector[i]; IndicesVector *allIndices = allIndicesSharedPtr.get(); unsigned int* indicesInRemapping = (unsigned int*)malloc(sizeof(unsigned int) * allIndices->size()); VertexAttributeVector vertexAttributes = sourcePrimitives[i]->getVertexAttributes(); for (unsigned int k = 0 ; k < allIndices->size() ; k++) { GLTF::Semantic semantic = vertexAttributes[k]->getSemantic(); unsigned int indexSet = vertexAttributes[k]->getIndexOfSet(); std::string semanticIndexSetKey = keyWithSemanticAndSet(semantic, indexSet); unsigned int idx = semanticAndSetToIndex[semanticIndexSetKey]; indicesInRemapping[k] = idx; } shared_ptr<GLTF::GLTFPrimitiveRemapInfos> primitiveRemapInfos = __BuildPrimitiveUniqueIndexes(targetPrimitives[i], *allIndices, remappedMeshIndexesMap, indicesInRemapping, startIndex, maxVertexAttributes, endIndex); free(indicesInRemapping); if (primitiveRemapInfos.get()) { startIndex = endIndex; allPrimitiveRemapInfos.push_back(primitiveRemapInfos); } else { // FIXME: report error //return NULL; } } // now we got not only the uniqueIndexes but also the number of different indexes, i.e the number of vertex attributes count // we can allocate the buffer to hold vertex attributes unsigned int vertexCount = endIndex; //just allocate it now, will be filled later unsigned int* remapTableForPositions = (unsigned int*)malloc(sizeof(unsigned int) * vertexCount); targetMesh->setRemapTableForPositions(remapTableForPositions); for (unsigned int i = 0 ; i < allSemantics.size() ; i++) { Semantic semantic = allSemantics[i]; IndexSetToMeshAttributeHashmap& indexSetToMeshAttribute = sourceMesh->getMeshAttributesForSemantic(semantic); IndexSetToMeshAttributeHashmap& destinationIndexSetToMeshAttribute = targetMesh->getMeshAttributesForSemantic(semantic); IndexSetToMeshAttributeHashmap::const_iterator meshAttributeIterator; //FIXME: consider turn this search into a method for mesh for (meshAttributeIterator = indexSetToMeshAttribute.begin() ; meshAttributeIterator != indexSetToMeshAttribute.end() ; meshAttributeIterator++) { //(*it).first; // the key value (of type Key) //(*it).second; // the mapped value (of type T) shared_ptr <GLTF::GLTFMeshAttribute> selectedMeshAttribute = (*meshAttributeIterator).second; size_t sourceSize = vertexCount * selectedMeshAttribute->getVertexAttributeByteLength(); void* sourceData = malloc(sourceSize); shared_ptr <GLTFBufferView> referenceBufferView = selectedMeshAttribute->getBufferView(); shared_ptr <GLTFBufferView> remappedBufferView = createBufferViewWithAllocatedBuffer(referenceBufferView->getID(), sourceData, 0, sourceSize, true); shared_ptr <GLTFMeshAttribute> remappedMeshAttribute(new GLTFMeshAttribute(selectedMeshAttribute.get())); remappedMeshAttribute->setBufferView(remappedBufferView); remappedMeshAttribute->setCount(vertexCount); destinationIndexSetToMeshAttribute[(*meshAttributeIterator).first] = remappedMeshAttribute; remappedMeshAttributes.push_back(remappedMeshAttribute); } } /* if (_allOriginalMeshAttributes.size() != allIndices.size()) { // FIXME: report error return false; } */ for (unsigned int i = 0 ; i < primitiveCount ; i++) { shared_ptr<IndicesVector> allIndicesSharedPtr = vectorOfIndicesVector[i]; IndicesVector *allIndices = allIndicesSharedPtr.get(); unsigned int* indicesInRemapping = (unsigned int*)calloc(sizeof(unsigned int) * (*allIndices).size(), 1); VertexAttributeVector vertexAttributes = sourcePrimitives[i]->getVertexAttributes(); for (unsigned int k = 0 ; k < (*allIndices).size() ; k++) { GLTF::Semantic semantic = vertexAttributes[k]->getSemantic(); unsigned int indexSet = vertexAttributes[k]->getIndexOfSet(); std::string semanticIndexSetKey = keyWithSemanticAndSet(semantic, indexSet); unsigned int idx = semanticAndSetToIndex[semanticIndexSetKey]; indicesInRemapping[k] = idx; } bool status = __RemapPrimitiveVertices(targetPrimitives[i], (*allIndices), originalMeshAttributes , remappedMeshAttributes, indicesInRemapping, allPrimitiveRemapInfos[i], remapTableForPositions); free(indicesInRemapping); if (!status) { // FIXME: report error //return NULL; } } return targetMesh; }