FOund the issue why the skinning was incorrect, removed unecessary data structures in the newly added objects and renamed Deformer to SkinCluster and DYnamicTransform to SkinDeformer

This commit is contained in:
Sam Gateau 2019-10-16 04:02:05 -07:00
parent f049ab7887
commit eecaeb1155
12 changed files with 110 additions and 104 deletions

View file

@ -30,8 +30,8 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) {
// we make a copy of the inverseBindMatrices in order to prevent mutating the model bind pose // we make a copy of the inverseBindMatrices in order to prevent mutating the model bind pose
// when we are dealing with a joint offset in the model // when we are dealing with a joint offset in the model
for (int i = 0; i < (int)hfmModel.dynamicTransforms.size(); i++) { for (int i = 0; i < (int)hfmModel.skinDeformers.size(); i++) {
const auto& defor = hfmModel.dynamicTransforms[i]; const auto& defor = hfmModel.skinDeformers[i];
std::vector<HFMCluster> dummyClustersList; std::vector<HFMCluster> dummyClustersList;
for (int j = 0; j < defor.clusters.size(); j++) { for (int j = 0; j < defor.clusters.size(); j++) {

View file

@ -1593,9 +1593,9 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const
// whether we're skinned depends on how many clusters are attached // whether we're skinned depends on how many clusters are attached
if (clusterIDs.size() > 0) { if (clusterIDs.size() > 0) {
hfm::DynamicTransform dynamicTransform; hfm::SkinDeformer skinDeformer;
auto& clusters = dynamicTransform.clusters; auto& clusters = skinDeformer.clusters;
std::vector<hfm::Deformer> deformers; std::vector<hfm::SkinCluster> skinClusters;
for (const auto& clusterID : clusterIDs) { for (const auto& clusterID : clusterIDs) {
HFMCluster hfmCluster; HFMCluster hfmCluster;
const Cluster& fbxCluster = fbxClusters[clusterID]; const Cluster& fbxCluster = fbxClusters[clusterID];
@ -1639,35 +1639,40 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const
clusters.push_back(cluster); clusters.push_back(cluster);
// Skinned mesh instances have a dynamic transform // Skinned mesh instances have a dynamic transform
dynamicTransform.deformers.reserve(clusterIDs.size()); skinDeformer.skinClusterIndices.reserve(clusterIDs.size());
clusters.reserve(clusterIDs.size());
for (const auto& clusterID : clusterIDs) { for (const auto& clusterID : clusterIDs) {
const Cluster& fbxCluster = fbxClusters[clusterID]; const Cluster& fbxCluster = fbxClusters[clusterID];
dynamicTransform.deformers.emplace_back(); skinDeformer.skinClusterIndices.emplace_back();
deformers.emplace_back(); skinClusters.emplace_back();
hfm::Deformer& deformer = deformers.back(); hfm::SkinCluster& skinCluster = skinClusters.back();
size_t indexWeightPairs = (size_t)std::min(fbxCluster.indices.size(), fbxCluster.weights.size()); size_t indexWeightPairs = (size_t)std::min(fbxCluster.indices.size(), fbxCluster.weights.size());
deformer.indices.reserve(indexWeightPairs); skinCluster.indices.reserve(indexWeightPairs);
deformer.weights.reserve(indexWeightPairs); skinCluster.weights.reserve(indexWeightPairs);
for (int i = 0; i < (int)indexWeightPairs; i++) {
int oldIndex = fbxCluster.indices[i]; for (int j = 0; j < fbxCluster.indices.size(); j++) {
uint32_t newIndex = (uint32_t)extracted.newIndices.value(oldIndex); int oldIndex = fbxCluster.indices.at(j);
deformer.indices.push_back(newIndex); float weight = fbxCluster.weights.at(j);
deformer.weights.push_back((float)fbxCluster.weights[i]); for (QMultiHash<int, int>::const_iterator it = extracted.newIndices.constFind(oldIndex);
it != extracted.newIndices.end() && it.key() == oldIndex; it++) {
int newIndex = it.value();
skinCluster.indices.push_back(newIndex);
skinCluster.weights.push_back(weight);
}
} }
} }
// Store this model's deformers, this dynamic transform's deformer IDs // Store this model's deformers, this dynamic transform's deformer IDs
uint32_t deformerMinID = (uint32_t)hfmModel.deformers.size(); uint32_t deformerMinID = (uint32_t)hfmModel.skinClusters.size();
hfmModel.deformers.insert(hfmModel.deformers.end(), deformers.cbegin(), deformers.cend()); hfmModel.skinClusters.insert(hfmModel.skinClusters.end(), skinClusters.cbegin(), skinClusters.cend());
dynamicTransform.deformers.resize(deformers.size()); skinDeformer.skinClusterIndices.resize(skinClusters.size());
std::iota(dynamicTransform.deformers.begin(), dynamicTransform.deformers.end(), deformerMinID); std::iota(skinDeformer.skinClusterIndices.begin(), skinDeformer.skinClusterIndices.end(), deformerMinID);
// Store the model's dynamic transform, and put its ID in the shapes // Store the model's dynamic transform, and put its ID in the shapes
hfmModel.dynamicTransforms.push_back(dynamicTransform); hfmModel.skinDeformers.push_back(skinDeformer);
uint32_t dynamicTransformID = (uint32_t)(hfmModel.dynamicTransforms.size() - 1); uint32_t skinDeformerID = (uint32_t)(hfmModel.skinDeformers.size() - 1);
for (hfm::Shape& shape : partShapes) { for (hfm::Shape& shape : partShapes) {
shape.dynamicTransform = dynamicTransformID; shape.skinDeformer = skinDeformerID;
} }
} else { } else {
// this is a no cluster mesh // this is a no cluster mesh

View file

@ -242,17 +242,20 @@ public:
QVector<glm::vec3> colors; QVector<glm::vec3> colors;
QVector<glm::vec2> texCoords; QVector<glm::vec2> texCoords;
QVector<glm::vec2> texCoords1; QVector<glm::vec2> texCoords1;
QVector<uint16_t> clusterIndices; // DEPRECATED (see hfm::Shape::dynamicTransform, hfm::DynamicTransform::deformers, hfm::Deformer)
QVector<uint16_t> clusterWeights; // DEPRECATED (see hfm::Shape::dynamicTransform, hfm::DynamicTransform::deformers, hfm::Deformer)
QVector<int32_t> originalIndices;
QVector<Cluster> clusters; // DEPRECATED (see hfm::Shape::dynamicTransform, hfm::DynamicTransform::clusters) QVector<Cluster> clusters; // DEPRECATED (see hfm::Shape::dynamicTransform, hfm::DynamicTransform::clusters)
Extents meshExtents; // DEPRECATED (see hfm::Shape::transformedExtents) Extents meshExtents; // DEPRECATED (see hfm::Shape::transformedExtents)
glm::mat4 modelTransform; // DEPRECATED (see hfm::Joint::globalTransform, hfm::Shape::transform, hfm::Model::joints) glm::mat4 modelTransform; // DEPRECATED (see hfm::Joint::globalTransform, hfm::Shape::transform, hfm::Model::joints)
// Skinning cluster attributes
QVector<uint16_t> clusterIndices;
QVector<uint16_t> clusterWeights;
// Blendshape attributes
QVector<Blendshape> blendshapes; QVector<Blendshape> blendshapes;
QVector<int32_t> originalIndices; // Original indices of the vertices
unsigned int meshIndex; // the order the meshes appeared in the object file unsigned int meshIndex; // the order the meshes appeared in the object file
graphics::MeshPointer _mesh; graphics::MeshPointer _mesh;
@ -294,18 +297,16 @@ public:
}; };
// Formerly contained in hfm::Mesh // Formerly contained in hfm::Mesh
class Deformer { class SkinCluster {
public: public:
std::vector<uint32_t> indices; std::vector<uint32_t> indices;
std::vector<float> weights; std::vector<float> weights;
}; };
class DynamicTransform { class SkinDeformer {
public: public:
std::vector<uint16_t> deformers; std::vector<uint16_t> skinClusterIndices;
std::vector<Cluster> clusters; // affect the deformer of the same index std::vector<Cluster> clusters;
std::vector<uint32_t> blendshapes;
// There are also the meshExtents and modelTransform, which for now are left in hfm::Mesh
}; };
// The lightweight model part description. // The lightweight model part description.
@ -317,7 +318,7 @@ public:
uint32_t joint { UNDEFINED_KEY }; // The hfm::Joint associated with this shape, containing transform information uint32_t joint { UNDEFINED_KEY }; // The hfm::Joint associated with this shape, containing transform information
// TODO: Have all serializers calculate hfm::Shape::transformedExtents in world space where they previously calculated hfm::Mesh::meshExtents. Change all code that uses hfm::Mesh::meshExtents to use this instead. // TODO: Have all serializers calculate hfm::Shape::transformedExtents in world space where they previously calculated hfm::Mesh::meshExtents. Change all code that uses hfm::Mesh::meshExtents to use this instead.
Extents transformedExtents; // The precise extents of the meshPart vertices in world space, after transform information is applied, while not taking into account rigging/skinning Extents transformedExtents; // The precise extents of the meshPart vertices in world space, after transform information is applied, while not taking into account rigging/skinning
uint32_t dynamicTransform { UNDEFINED_KEY }; uint32_t skinDeformer { UNDEFINED_KEY };
}; };
/// The runtime model format. /// The runtime model format.
@ -334,9 +335,9 @@ public:
std::vector<Mesh> meshes; std::vector<Mesh> meshes;
std::vector<Material> materials; std::vector<Material> materials;
std::vector<Deformer> deformers;
std::vector<DynamicTransform> dynamicTransforms; std::vector<SkinDeformer> skinDeformers;
std::vector<SkinCluster> skinClusters;
std::vector<Joint> joints; std::vector<Joint> joints;
QHash<QString, int> jointIndices; ///< 1-based, so as to more easily detect missing indices QHash<QString, int> jointIndices; ///< 1-based, so as to more easily detect missing indices

View file

@ -29,7 +29,7 @@ namespace baker {
class GetModelPartsTask { class GetModelPartsTask {
public: public:
using Input = hfm::Model::Pointer; using Input = hfm::Model::Pointer;
using Output = VaryingSet8<std::vector<hfm::Mesh>, hifi::URL, baker::MeshIndicesToModelNames, baker::BlendshapesPerMesh, std::vector<hfm::Joint>, std::vector<hfm::Shape>, std::vector<hfm::DynamicTransform>, std::vector<hfm::Deformer>>; using Output = VaryingSet8<std::vector<hfm::Mesh>, hifi::URL, baker::MeshIndicesToModelNames, baker::BlendshapesPerMesh, std::vector<hfm::Joint>, std::vector<hfm::Shape>, std::vector<hfm::SkinDeformer>, std::vector<hfm::SkinCluster>>;
using JobModel = Job::ModelIO<GetModelPartsTask, Input, Output>; using JobModel = Job::ModelIO<GetModelPartsTask, Input, Output>;
void run(const BakeContextPointer& context, const Input& input, Output& output) { void run(const BakeContextPointer& context, const Input& input, Output& output) {
@ -44,8 +44,8 @@ namespace baker {
} }
output.edit4() = hfmModelIn->joints; output.edit4() = hfmModelIn->joints;
output.edit5() = hfmModelIn->shapes; output.edit5() = hfmModelIn->shapes;
output.edit6() = hfmModelIn->dynamicTransforms; output.edit6() = hfmModelIn->skinDeformers;
output.edit7() = hfmModelIn->deformers; output.edit7() = hfmModelIn->skinClusters;
} }
}; };
@ -143,7 +143,7 @@ namespace baker {
const auto blendshapesPerMeshIn = modelPartsIn.getN<GetModelPartsTask::Output>(3); const auto blendshapesPerMeshIn = modelPartsIn.getN<GetModelPartsTask::Output>(3);
const auto jointsIn = modelPartsIn.getN<GetModelPartsTask::Output>(4); const auto jointsIn = modelPartsIn.getN<GetModelPartsTask::Output>(4);
const auto shapesIn = modelPartsIn.getN<GetModelPartsTask::Output>(5); const auto shapesIn = modelPartsIn.getN<GetModelPartsTask::Output>(5);
const auto dynamicTransformsIn = modelPartsIn.getN<GetModelPartsTask::Output>(6); const auto skinDeformersIn = modelPartsIn.getN<GetModelPartsTask::Output>(6);
const auto deformersIn = modelPartsIn.getN<GetModelPartsTask::Output>(7); const auto deformersIn = modelPartsIn.getN<GetModelPartsTask::Output>(7);
// Calculate normals and tangents for meshes and blendshapes if they do not exist // Calculate normals and tangents for meshes and blendshapes if they do not exist
@ -158,14 +158,14 @@ namespace baker {
// Skinning weight calculations // Skinning weight calculations
// NOTE: Due to limitations in the current graphics::MeshPointer representation, the output list of ReweightedDeformers is per-mesh. An element is empty if there are no deformers for the mesh of the same index. // NOTE: Due to limitations in the current graphics::MeshPointer representation, the output list of ReweightedDeformers is per-mesh. An element is empty if there are no deformers for the mesh of the same index.
const auto reweightDeformersInputs = ReweightDeformersTask::Input(meshesIn, shapesIn, dynamicTransformsIn, deformersIn).asVarying(); const auto reweightDeformersInputs = ReweightDeformersTask::Input(meshesIn, shapesIn, skinDeformersIn, deformersIn).asVarying();
const auto reweightedDeformers = model.addJob<ReweightDeformersTask>("ReweightDeformers", reweightDeformersInputs); const auto reweightedDeformers = model.addJob<ReweightDeformersTask>("ReweightDeformers", reweightDeformersInputs);
// Shape vertices are included/rejected based on skinning weight, and thus must use the reweighted deformers. // Shape vertices are included/rejected based on skinning weight, and thus must use the reweighted deformers.
const auto collectShapeVerticesInputs = CollectShapeVerticesTask::Input(meshesIn, shapesIn, jointsIn, dynamicTransformsIn, reweightedDeformers).asVarying(); const auto collectShapeVerticesInputs = CollectShapeVerticesTask::Input(meshesIn, shapesIn, jointsIn, skinDeformersIn, reweightedDeformers).asVarying();
const auto shapeVerticesPerJoint = model.addJob<CollectShapeVerticesTask>("CollectShapeVertices", collectShapeVerticesInputs); const auto shapeVerticesPerJoint = model.addJob<CollectShapeVerticesTask>("CollectShapeVertices", collectShapeVerticesInputs);
// Build the graphics::MeshPointer for each hfm::Mesh // Build the graphics::MeshPointer for each hfm::Mesh
const auto buildGraphicsMeshInputs = BuildGraphicsMeshTask::Input(meshesIn, url, meshIndicesToModelNames, normalsPerMesh, tangentsPerMesh, shapesIn, dynamicTransformsIn, reweightedDeformers).asVarying(); const auto buildGraphicsMeshInputs = BuildGraphicsMeshTask::Input(meshesIn, url, meshIndicesToModelNames, normalsPerMesh, tangentsPerMesh, shapesIn, skinDeformersIn, reweightedDeformers).asVarying();
const auto graphicsMeshes = model.addJob<BuildGraphicsMeshTask>("BuildGraphicsMesh", buildGraphicsMeshInputs); const auto graphicsMeshes = model.addJob<BuildGraphicsMeshTask>("BuildGraphicsMesh", buildGraphicsMeshInputs);
// Prepare joint information // Prepare joint information

View file

@ -381,16 +381,16 @@ void BuildGraphicsMeshTask::run(const baker::BakeContextPointer& context, const
const auto& normalsPerMesh = input.get3(); const auto& normalsPerMesh = input.get3();
const auto& tangentsPerMesh = input.get4(); const auto& tangentsPerMesh = input.get4();
const auto& shapes = input.get5(); const auto& shapes = input.get5();
const auto& dynamicTransforms = input.get6(); const auto& skinDeformers = input.get6();
const auto& reweightedDeformersPerMesh = input.get7(); const auto& reweightedDeformersPerMesh = input.get7();
// Currently, there is only (at most) one dynamicTransform per mesh // Currently, there is only (at most) one skinDeformer per mesh
// An undefined shape.dynamicTransform has the value hfm::UNDEFINED_KEY // An undefined shape.skinDeformer has the value hfm::UNDEFINED_KEY
std::vector<uint32_t> dynamicTransformPerMesh; std::vector<uint32_t> skinDeformerPerMesh;
dynamicTransformPerMesh.resize(meshes.size(), hfm::UNDEFINED_KEY); skinDeformerPerMesh.resize(meshes.size(), hfm::UNDEFINED_KEY);
for (const auto& shape : shapes) { for (const auto& shape : shapes) {
uint32_t dynamicTransformIndex = shape.dynamicTransform; uint32_t skinDeformerIndex = shape.skinDeformer;
dynamicTransformPerMesh[shape.mesh] = dynamicTransformIndex; skinDeformerPerMesh[shape.mesh] = skinDeformerIndex;
} }
auto& graphicsMeshes = output; auto& graphicsMeshes = output;
@ -403,10 +403,10 @@ void BuildGraphicsMeshTask::run(const baker::BakeContextPointer& context, const
uint16_t numDeformerControllers = 0; uint16_t numDeformerControllers = 0;
if (reweightedDeformers.weightsPerVertex != 0) { if (reweightedDeformers.weightsPerVertex != 0) {
uint32_t dynamicTransformIndex = dynamicTransformPerMesh[i]; uint32_t skinDeformerIndex = skinDeformerPerMesh[i];
if (dynamicTransformIndex != hfm::UNDEFINED_KEY) { if (skinDeformerIndex != hfm::UNDEFINED_KEY) {
const hfm::DynamicTransform& dynamicTransform = dynamicTransforms[dynamicTransformIndex]; const hfm::SkinDeformer& skinDeformer = skinDeformers[skinDeformerIndex];
numDeformerControllers = (uint16_t)dynamicTransform.deformers.size(); numDeformerControllers = (uint16_t)skinDeformer.skinClusterIndices.size();
} }
} }

View file

@ -20,7 +20,7 @@
class BuildGraphicsMeshTask { class BuildGraphicsMeshTask {
public: public:
using Input = baker::VaryingSet8<std::vector<hfm::Mesh>, hifi::URL, baker::MeshIndicesToModelNames, baker::NormalsPerMesh, baker::TangentsPerMesh, std::vector<hfm::Shape>, std::vector<hfm::DynamicTransform>, std::vector<baker::ReweightedDeformers>>; using Input = baker::VaryingSet8<std::vector<hfm::Mesh>, hifi::URL, baker::MeshIndicesToModelNames, baker::NormalsPerMesh, baker::TangentsPerMesh, std::vector<hfm::Shape>, std::vector<hfm::SkinDeformer>, std::vector<baker::ReweightedDeformers>>;
using Output = std::vector<graphics::MeshPointer>; using Output = std::vector<graphics::MeshPointer>;
using JobModel = baker::Job::ModelIO<BuildGraphicsMeshTask, Input, Output>; using JobModel = baker::Job::ModelIO<BuildGraphicsMeshTask, Input, Output>;

View file

@ -13,15 +13,15 @@
#include <glm/gtx/transform.hpp> #include <glm/gtx/transform.hpp>
// Used to track and avoid duplicate shape vertices, as multiple shapes can have the same mesh and dynamicTransform // Used to track and avoid duplicate shape vertices, as multiple shapes can have the same mesh and skinDeformer
class VertexSource { class VertexSource {
public: public:
uint32_t mesh; uint32_t mesh;
uint32_t dynamicTransform; uint32_t skinDeformer;
bool operator==(const VertexSource& other) const { bool operator==(const VertexSource& other) const {
return mesh == other.mesh && return mesh == other.mesh &&
dynamicTransform == other.dynamicTransform; skinDeformer == other.skinDeformer;
} }
}; };
@ -29,7 +29,7 @@ void CollectShapeVerticesTask::run(const baker::BakeContextPointer& context, con
const auto& meshes = input.get0(); const auto& meshes = input.get0();
const auto& shapes = input.get1(); const auto& shapes = input.get1();
const auto& joints = input.get2(); const auto& joints = input.get2();
const auto& dynamicTransforms = input.get3(); const auto& skinDeformers = input.get3();
const auto& reweightedDeformers = input.get4(); const auto& reweightedDeformers = input.get4();
auto& shapeVerticesPerJoint = output; auto& shapeVerticesPerJoint = output;
@ -38,18 +38,18 @@ void CollectShapeVerticesTask::run(const baker::BakeContextPointer& context, con
vertexSourcesPerJoint.resize(joints.size()); vertexSourcesPerJoint.resize(joints.size());
for (size_t i = 0; i < shapes.size(); ++i) { for (size_t i = 0; i < shapes.size(); ++i) {
const auto& shape = shapes[i]; const auto& shape = shapes[i];
const uint32_t dynamicTransformKey = shape.dynamicTransform; const uint32_t skinDeformerKey = shape.skinDeformer;
if (dynamicTransformKey == hfm::UNDEFINED_KEY) { if (skinDeformerKey == hfm::UNDEFINED_KEY) {
continue; continue;
} }
VertexSource vertexSource; VertexSource vertexSource;
vertexSource.mesh = shape.mesh; vertexSource.mesh = shape.mesh;
vertexSource.dynamicTransform = dynamicTransformKey; vertexSource.skinDeformer = skinDeformerKey;
const auto& dynamicTransform = dynamicTransforms[dynamicTransformKey]; const auto& skinDeformer = skinDeformers[skinDeformerKey];
for (size_t j = 0; j < dynamicTransform.clusters.size(); ++j) { for (size_t j = 0; j < skinDeformer.clusters.size(); ++j) {
const auto& cluster = dynamicTransform.clusters[j]; const auto& cluster = skinDeformer.clusters[j];
const uint32_t jointIndex = cluster.jointIndex; const uint32_t jointIndex = cluster.jointIndex;
auto& vertexSources = vertexSourcesPerJoint[jointIndex]; auto& vertexSources = vertexSourcesPerJoint[jointIndex];

View file

@ -19,7 +19,7 @@
class CollectShapeVerticesTask { class CollectShapeVerticesTask {
public: public:
using Input = baker::VaryingSet5<std::vector<hfm::Mesh>, std::vector<hfm::Shape>, std::vector<hfm::Joint>, std::vector<hfm::DynamicTransform>, std::vector<baker::ReweightedDeformers>>; using Input = baker::VaryingSet5<std::vector<hfm::Mesh>, std::vector<hfm::Shape>, std::vector<hfm::Joint>, std::vector<hfm::SkinDeformer>, std::vector<baker::ReweightedDeformers>>;
using Output = std::vector<ShapeVertices>; using Output = std::vector<ShapeVertices>;
using JobModel = baker::Job::ModelIO<CollectShapeVerticesTask, Input, Output>; using JobModel = baker::Job::ModelIO<CollectShapeVerticesTask, Input, Output>;

View file

@ -11,30 +11,30 @@
#include "ReweightDeformersTask.h" #include "ReweightDeformersTask.h"
baker::ReweightedDeformers getReweightedDeformers(size_t numMeshVertices, const std::vector<const hfm::Deformer*> deformers, const uint16_t weightsPerVertex) { baker::ReweightedDeformers getReweightedDeformers(size_t numMeshVertices, const std::vector<const hfm::SkinCluster*> skinClusters, const uint16_t weightsPerVertex) {
baker::ReweightedDeformers reweightedDeformers; baker::ReweightedDeformers reweightedDeformers;
if (deformers.size() == 0) { if (skinClusters.size() == 0) {
return reweightedDeformers; return reweightedDeformers;
} }
size_t numClusterIndices = numMeshVertices * weightsPerVertex; size_t numClusterIndices = numMeshVertices * weightsPerVertex;
reweightedDeformers.weightsPerVertex = weightsPerVertex; reweightedDeformers.weightsPerVertex = weightsPerVertex;
// TODO: Consider having a rootCluster property in the DynamicTransform rather than appending the root to the end of the cluster list. // TODO: Consider having a rootCluster property in the DynamicTransform rather than appending the root to the end of the cluster list.
reweightedDeformers.indices.resize(numClusterIndices, (uint16_t)(deformers.size() - 1)); reweightedDeformers.indices.resize(numClusterIndices, (uint16_t)(skinClusters.size() - 1));
reweightedDeformers.weights.resize(numClusterIndices, 0); reweightedDeformers.weights.resize(numClusterIndices, 0);
std::vector<float> weightAccumulators; std::vector<float> weightAccumulators;
weightAccumulators.resize(numClusterIndices, 0.0f); weightAccumulators.resize(numClusterIndices, 0.0f);
for (uint16_t i = 0; i < (uint16_t)deformers.size(); ++i) { for (uint16_t i = 0; i < (uint16_t)skinClusters.size(); ++i) {
const hfm::Deformer& deformer = *deformers[i]; const hfm::SkinCluster& skinCluster = *skinClusters[i];
if (deformer.indices.size() != deformer.weights.size()) { if (skinCluster.indices.size() != skinCluster.weights.size()) {
reweightedDeformers.trimmedToMatch = true; reweightedDeformers.trimmedToMatch = true;
} }
size_t numIndicesOrWeights = std::min(deformer.indices.size(), deformer.weights.size()); size_t numIndicesOrWeights = std::min(skinCluster.indices.size(), skinCluster.weights.size());
for (size_t j = 0; j < numIndicesOrWeights; ++j) { for (size_t j = 0; j < numIndicesOrWeights; ++j) {
uint32_t index = deformer.indices[j]; uint32_t index = skinCluster.indices[j];
float weight = deformer.weights[j]; float weight = skinCluster.weights[j];
// look for an unused slot in the weights vector // look for an unused slot in the weights vector
uint32_t weightIndex = index * weightsPerVertex; uint32_t weightIndex = index * weightsPerVertex;
@ -90,34 +90,34 @@ void ReweightDeformersTask::run(const baker::BakeContextPointer& context, const
const auto& meshes = input.get0(); const auto& meshes = input.get0();
const auto& shapes = input.get1(); const auto& shapes = input.get1();
const auto& dynamicTransforms = input.get2(); const auto& skinDeformers = input.get2();
const auto& deformers = input.get3(); const auto& skinClusters = input.get3();
auto& reweightedDeformers = output; auto& reweightedDeformers = output;
// Currently, there is only (at most) one dynamicTransform per mesh // Currently, there is only (at most) one skinDeformer per mesh
// An undefined shape.dynamicTransform has the value hfm::UNDEFINED_KEY // An undefined shape.skinDeformer has the value hfm::UNDEFINED_KEY
std::vector<uint32_t> dynamicTransformPerMesh; std::vector<uint32_t> skinDeformerPerMesh;
dynamicTransformPerMesh.resize(meshes.size(), hfm::UNDEFINED_KEY); skinDeformerPerMesh.resize(meshes.size(), hfm::UNDEFINED_KEY);
for (const auto& shape : shapes) { for (const auto& shape : shapes) {
uint32_t dynamicTransformIndex = shape.dynamicTransform; uint32_t skinDeformerIndex = shape.skinDeformer;
dynamicTransformPerMesh[shape.mesh] = dynamicTransformIndex; skinDeformerPerMesh[shape.mesh] = skinDeformerIndex;
} }
reweightedDeformers.reserve(meshes.size()); reweightedDeformers.reserve(meshes.size());
for (size_t i = 0; i < meshes.size(); ++i) { for (size_t i = 0; i < meshes.size(); ++i) {
const auto& mesh = meshes[i]; const auto& mesh = meshes[i];
uint32_t dynamicTransformIndex = dynamicTransformPerMesh[i]; uint32_t skinDeformerIndex = skinDeformerPerMesh[i];
const hfm::DynamicTransform* dynamicTransform = nullptr; const hfm::SkinDeformer* skinDeformer = nullptr;
std::vector<const hfm::Deformer*> meshDeformers; std::vector<const hfm::SkinCluster*> meshSkinClusters;
if (dynamicTransformIndex != hfm::UNDEFINED_KEY) { if (skinDeformerIndex != hfm::UNDEFINED_KEY) {
dynamicTransform = &dynamicTransforms[dynamicTransformIndex]; skinDeformer = &skinDeformers[skinDeformerIndex];
for (const auto& deformerIndex : dynamicTransform->deformers) { for (const auto& skinClusterIndex : skinDeformer->skinClusterIndices) {
const auto& deformer = deformers[deformerIndex]; const auto& skinCluster = skinClusters[skinClusterIndex];
meshDeformers.push_back(&deformer); meshSkinClusters.push_back(&skinCluster);
} }
} }
reweightedDeformers.push_back(getReweightedDeformers((size_t)mesh.vertices.size(), meshDeformers, NUM_WEIGHTS_PER_VERTEX)); reweightedDeformers.push_back(getReweightedDeformers((size_t)mesh.vertices.size(), meshSkinClusters, NUM_WEIGHTS_PER_VERTEX));
} }
} }

View file

@ -19,7 +19,7 @@
class ReweightDeformersTask { class ReweightDeformersTask {
public: public:
using Input = baker::VaryingSet4<std::vector<hfm::Mesh>, std::vector<hfm::Shape>, std::vector<hfm::DynamicTransform>, std::vector<hfm::Deformer>>; using Input = baker::VaryingSet4<std::vector<hfm::Mesh>, std::vector<hfm::Shape>, std::vector<hfm::SkinDeformer>, std::vector<hfm::SkinCluster>>;
using Output = std::vector<baker::ReweightedDeformers>; using Output = std::vector<baker::ReweightedDeformers>;
using JobModel = baker::Job::ModelIO<ReweightDeformersTask, Input, Output>; using JobModel = baker::Job::ModelIO<ReweightDeformersTask, Input, Output>;

View file

@ -33,7 +33,7 @@ bool CauterizedModel::updateGeometry() {
if (_isCauterized && needsFullUpdate) { if (_isCauterized && needsFullUpdate) {
assert(_cauterizeMeshStates.empty()); assert(_cauterizeMeshStates.empty());
/* const HFMModel& hfmModel = getHFMModel(); /* const HFMModel& hfmModel = getHFMModel();
const auto& hfmDynamicTransforms = hfmModel.dynamicTransforms; const auto& hfmDynamicTransforms = hfmModel.skinDeformers;
for (int i = 0; i < hfmDynamicTransforms.size(); i++) { for (int i = 0; i < hfmDynamicTransforms.size(); i++) {
const auto& dynT = hfmDynamicTransforms[i]; const auto& dynT = hfmDynamicTransforms[i];
MeshState state; MeshState state;
@ -47,7 +47,7 @@ bool CauterizedModel::updateGeometry() {
}*/ }*/
const HFMModel& hfmModel = getHFMModel(); const HFMModel& hfmModel = getHFMModel();
const auto& hfmDynamicTransforms = hfmModel.dynamicTransforms; const auto& hfmDynamicTransforms = hfmModel.skinDeformers;
int i = 0; int i = 0;
/* for (const auto& mesh: hfmModel.meshes) { /* for (const auto& mesh: hfmModel.meshes) {
MeshState state; MeshState state;
@ -113,7 +113,7 @@ void CauterizedModel::createRenderItemSet() {
auto material = getNetworkModel()->getShapeMaterial(shapeID); auto material = getNetworkModel()->getShapeMaterial(shapeID);
_modelMeshMaterialNames.push_back(material ? material->getName() : ""); _modelMeshMaterialNames.push_back(material ? material->getName() : "");
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)shape.mesh, shape.dynamicTransform }); _modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)shape.mesh, shape.skinDeformer });
} }
/* int shapeID = 0; /* int shapeID = 0;
@ -153,7 +153,7 @@ void CauterizedModel::updateClusterMatrices() {
const HFMModel& hfmModel = getHFMModel(); const HFMModel& hfmModel = getHFMModel();
const auto& hfmDynamicTransforms = hfmModel.dynamicTransforms; const auto& hfmDynamicTransforms = hfmModel.skinDeformers;
for (int i = 0; i < (int)_meshStates.size(); i++) { for (int i = 0; i < (int)_meshStates.size(); i++) {
MeshState& state = _meshStates[i]; MeshState& state = _meshStates[i];
const auto& deformer = hfmDynamicTransforms[i]; const auto& deformer = hfmDynamicTransforms[i];

View file

@ -336,7 +336,7 @@ bool Model::updateGeometry() {
updateShapeStatesFromRig(); updateShapeStatesFromRig();
const HFMModel& hfmModel = getHFMModel(); const HFMModel& hfmModel = getHFMModel();
const auto& hfmDynamicTransforms = hfmModel.dynamicTransforms; const auto& hfmSkinDeformers = hfmModel.skinDeformers;
int i = 0; int i = 0;
/* for (const auto& mesh: hfmModel.meshes) { /* for (const auto& mesh: hfmModel.meshes) {
MeshState state; MeshState state;
@ -346,8 +346,8 @@ bool Model::updateGeometry() {
i++; i++;
} }
*/ */
for (int i = 0; i < hfmDynamicTransforms.size(); i++) { for (int i = 0; i < hfmSkinDeformers.size(); i++) {
const auto& dynT = hfmDynamicTransforms[i]; const auto& dynT = hfmSkinDeformers[i];
MeshState state; MeshState state;
state.clusterDualQuaternions.resize(dynT.clusters.size()); state.clusterDualQuaternions.resize(dynT.clusters.size());
state.clusterMatrices.resize(dynT.clusters.size()); state.clusterMatrices.resize(dynT.clusters.size());
@ -1427,10 +1427,10 @@ void Model::updateClusterMatrices() {
_needsUpdateClusterMatrices = false; _needsUpdateClusterMatrices = false;
const HFMModel& hfmModel = getHFMModel(); const HFMModel& hfmModel = getHFMModel();
const auto& hfmDynamicTransforms = hfmModel.dynamicTransforms; const auto& hfmSkinDeformers = hfmModel.skinDeformers;
for (int i = 0; i < (int) _meshStates.size(); i++) { for (int i = 0; i < (int) _meshStates.size(); i++) {
MeshState& state = _meshStates[i]; MeshState& state = _meshStates[i];
const auto& deformer = hfmDynamicTransforms[i]; const auto& deformer = hfmSkinDeformers[i];
int meshIndex = i; int meshIndex = i;
int clusterIndex = 0; int clusterIndex = 0;
@ -1545,7 +1545,7 @@ void Model::createRenderItemSet() {
auto material = getNetworkModel()->getShapeMaterial(shapeID); auto material = getNetworkModel()->getShapeMaterial(shapeID);
_modelMeshMaterialNames.push_back(material ? material->getName() : ""); _modelMeshMaterialNames.push_back(material ? material->getName() : "");
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)shape.mesh, shape.dynamicTransform }); _modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)shape.mesh, shape.skinDeformer });
} }
/* /*
uint32_t numMeshes = (uint32_t)meshes.size(); uint32_t numMeshes = (uint32_t)meshes.size();