diff --git a/parts/mdl/mdlimport.cpp b/parts/mdl/mdlimport.cpp index 3f68adc..60e8963 100644 --- a/parts/mdl/mdlimport.cpp +++ b/parts/mdl/mdlimport.cpp @@ -47,16 +47,26 @@ void importModel(physis_MDL &existingModel, const QString &filename) auto &mesh = model.meshes[node.mesh]; auto &primitive = mesh.primitives[0]; + const auto getAccessor = [&model, &primitive](const std::string &name, const int index) -> unsigned char const * { + const auto &positionAccessor = model.accessors[primitive.attributes[name]]; + const auto &positionView = model.bufferViews[positionAccessor.bufferView]; + const auto &positionBuffer = model.buffers[positionView.buffer]; + + int elementCount = tinygltf::GetNumComponentsInType(positionAccessor.type); + int elementSize = tinygltf::GetComponentSizeInBytes(positionAccessor.componentType); + + return (positionBuffer.data.data() + (std::max(positionView.byteStride, (size_t)elementCount * elementSize) * index) + positionView.byteOffset + + positionAccessor.byteOffset); + }; + // All of the accessors are mapped to the same buffer vertex view - const auto &vertexAccessor = model.accessors[primitive.attributes["POSITION"]]; - const auto &vertexView = model.bufferViews[vertexAccessor.bufferView]; - const auto &vertexBuffer = model.buffers[vertexView.buffer]; + const auto &positionAccessor = model.accessors[primitive.attributes["POSITION"]]; const auto &indexAccessor = model.accessors[primitive.indices]; const auto &indexView = model.bufferViews[indexAccessor.bufferView]; const auto &indexBuffer = model.buffers[indexView.buffer]; - const int newVertexCount = vertexAccessor.count; + const int newVertexCount = positionAccessor.count; const int oldVertexCount = existingModel.lods[lodNumber].parts[partNumber].num_vertices; if (newVertexCount != oldVertexCount) { @@ -70,12 +80,16 @@ void importModel(physis_MDL &existingModel, const QString &filename) qInfo() << "- Difference in index count!" << newIndexCount << "old:" << oldIndexCount; } - qInfo() << "- Importing mesh of" << vertexAccessor.count << "vertices and" << indexAccessor.count << "indices."; + qInfo() << "- Importing mesh of" << positionAccessor.count << "vertices and" << indexAccessor.count << "indices."; std::vector newVertices; - for (uint32_t i = 0; i < vertexAccessor.count; i++) { - auto vertexData = (glm::vec3 *)(vertexBuffer.data.data() + (std::max(vertexView.byteStride, sizeof(float) * 3) * i) + vertexView.byteOffset - + vertexAccessor.byteOffset); + for (uint32_t i = 0; i < positionAccessor.count; i++) { + glm::vec3 const *positionData = reinterpret_cast(getAccessor("POSITION", i)); + glm::vec3 const *normalData = reinterpret_cast(getAccessor("NORMAL", i)); + glm::vec2 const *uv0Data = reinterpret_cast(getAccessor("TEXCOORD_0", i)); + glm::vec2 const *uv1Data = reinterpret_cast(getAccessor("TEXCOORD_1", i)); + glm::vec4 const *weightsData = reinterpret_cast(getAccessor("WEIGHTS_0", i)); + uint8_t const *jointsData = reinterpret_cast(getAccessor("JOINTS_0", i)); // Replace position data Vertex vertex{}; @@ -83,9 +97,42 @@ void importModel(physis_MDL &existingModel, const QString &filename) vertex = existingModel.lods[lodNumber].parts[partNumber].vertices[i]; } - vertex.position[0] = vertexData->x; - vertex.position[1] = vertexData->y; - vertex.position[2] = vertexData->z; + vertex.position[0] = positionData->x; + vertex.position[1] = positionData->y; + vertex.position[2] = positionData->z; + + vertex.normal[0] = normalData->x; + vertex.normal[1] = normalData->y; + vertex.normal[2] = normalData->z; + + vertex.uv0[0] = uv0Data->x; + vertex.uv0[1] = uv0Data->y; + + vertex.uv1[0] = uv1Data->x; + vertex.uv1[1] = uv1Data->y; + + vertex.bone_weight[0] = weightsData->x; + vertex.bone_weight[1] = weightsData->y; + vertex.bone_weight[2] = weightsData->z; + vertex.bone_weight[3] = weightsData->w; + + // We need to ensure the bones are mapped correctly + // When exporting from modeling software, it's possible it sorted the nodes (Blender does this) + for (int i = 0; i < 4; i++) { + int originalBoneId = *(jointsData + i); + + auto joints = model.skins[0].joints; + + int realBoneId = 0; + for (int j = 0; j < existingModel.num_affected_bones; j++) { + if (strcmp(existingModel.affected_bone_names[j], model.nodes[joints[originalBoneId]].name.c_str()) == 0) { + realBoneId = j; + break; + } + } + + vertex.bone_id[i] = realBoneId; + } newVertices.push_back(vertex); }