Fixed blendshapes from gltf

This commit is contained in:
ksuprynowicz 2024-02-28 22:44:16 +01:00
parent a1089b5b50
commit 8e51664b69

View file

@ -125,7 +125,7 @@ bool GLTFSerializer::generateTargetData(cgltf_accessor *accessor, float weight,
} }
storedValues.resize(accessor->count * 3); storedValues.resize(accessor->count * 3);
size_t numFloats = cgltf_accessor_unpack_floats(accessor, storedValues.data(), accessor->count * 3); size_t numFloats = cgltf_accessor_unpack_floats(accessor, storedValues.data(), accessor->count * 3);
if (numFloats == accessor->count * 3) { if (numFloats != accessor->count * 3) {
return false; return false;
} }
@ -158,7 +158,7 @@ template<typename T> bool findPointerInArray(const T *pointer, const T *array, s
bool findAttribute(const QString &name, const cgltf_attribute *attributes, size_t numAttributes, size_t &index) { bool findAttribute(const QString &name, const cgltf_attribute *attributes, size_t numAttributes, size_t &index) {
std::string nameString = name.toStdString(); std::string nameString = name.toStdString();
for (size_t i = 0; i < numAttributes; i++) { for (size_t i = 0; i < numAttributes; i++) {
if (strcmp(nameString.c_str(), attributes->name) != 0) { if (strcmp(nameString.c_str(), attributes->name) == 0) {
index = i; index = i;
return true; return true;
} }
@ -212,27 +212,29 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
// therefore we need to re-initialize the order in which nodes will be parsed // therefore we need to re-initialize the order in which nodes will be parsed
QVector<bool> hasBeenSorted; QVector<bool> hasBeenSorted;
hasBeenSorted.fill(false, numNodes); hasBeenSorted.fill(false, numNodes);
size_t i = 0; // initial index {
while (i < numNodes) { size_t i = 0; // initial index
int currentNode = sortedNodes[i]; while (i < numNodes) {
int parentIndex = parents[currentNode]; int currentNode = sortedNodes[i];
if (parentIndex == -1 || hasBeenSorted[parentIndex]) { int parentIndex = parents[currentNode];
hasBeenSorted[currentNode] = true; if (parentIndex == -1 || hasBeenSorted[parentIndex]) {
++i; hasBeenSorted[currentNode] = true;
} else { ++i;
size_t j = i + 1; // index of node to be sorted } else {
while (j < numNodes) { size_t j = i + 1; // index of node to be sorted
int nextNode = sortedNodes[j]; while (j < numNodes) {
parentIndex = parents[nextNode]; int nextNode = sortedNodes[j];
if (parentIndex == -1 || hasBeenSorted[parentIndex]) { parentIndex = parents[nextNode];
// swap with currentNode if (parentIndex == -1 || hasBeenSorted[parentIndex]) {
hasBeenSorted[nextNode] = true; // swap with currentNode
sortedNodes[i] = nextNode; hasBeenSorted[nextNode] = true;
sortedNodes[j] = currentNode; sortedNodes[i] = nextNode;
++i; sortedNodes[j] = currentNode;
currentNode = sortedNodes[i]; ++i;
currentNode = sortedNodes[i];
}
++j;
} }
++j;
} }
} }
} }
@ -971,7 +973,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
} }
// Build morph targets (blend shapes) // Build morph targets (blend shapes)
if (!primitive.targets_count) { if (primitive.targets_count) {
// Build list of blendshapes from FST and model. // Build list of blendshapes from FST and model.
typedef QPair<int, float> WeightedIndex; typedef QPair<int, float> WeightedIndex;
@ -993,8 +995,8 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
} else { } else {
// Use blendshape from model. // Use blendshape from model.
std::string blendshapeNameString = blendshapeName.toStdString(); std::string blendshapeNameString = blendshapeName.toStdString();
for (size_t i = 0; i < node.mesh->target_names_count; i++) { for (size_t j = 0; j < node.mesh->target_names_count; j++) {
if (strcmp(node.mesh->target_names[i], blendshapeNameString.c_str()) == 0) { if (strcmp(node.mesh->target_names[j], blendshapeNameString.c_str()) == 0) {
blendshapeIndices.insert(blendshapeName, WeightedIndex(i, 1.0f)); blendshapeIndices.insert(blendshapeName, WeightedIndex(i, 1.0f));
break; break;
} }
@ -1089,12 +1091,23 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
blendshape.vertices.resize(prevMeshVerticesCount + vertices.size()); blendshape.vertices.resize(prevMeshVerticesCount + vertices.size());
blendshape.normals.resize(prevMeshVerticesCount + vertices.size()); blendshape.normals.resize(prevMeshVerticesCount + vertices.size());
} }
//TODO: it looks like this can support sparse encoding, since there are indices?
for (int i = 0; i < vertices.size(); i++) { for (int i = 0; i < vertices.size(); i++) {
blendshape.indices[prevMeshVerticesCount + i] = prevMeshVerticesCount + i; blendshape.indices[prevMeshVerticesCount + i] = prevMeshVerticesCount + i;
blendshape.vertices[prevMeshVerticesCount + i] += vertices.value(i); blendshape.vertices[prevMeshVerticesCount + i] += vertices.value(i);
blendshape.normals[prevMeshVerticesCount + i] += normals.value(i); // Prevent out-of-bounds access if blendshape normals are not available
if (i < normals.size()) {
blendshape.normals[prevMeshVerticesCount + i] += normals.value(i);
} else {
if (prevMeshVerticesCount + i < mesh.normals.size()) {
blendshape.normals[prevMeshVerticesCount + i] = mesh.normals[prevMeshVerticesCount + i];
} else {
qWarning(modelformat) << "Blendshape has more vertices than original mesh " << _url;
hfmModel.loadErrorCount++;
return false;
}
}
} }
} }
} }