mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 07:27:04 +02:00
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:
parent
f049ab7887
commit
eecaeb1155
12 changed files with 110 additions and 104 deletions
|
@ -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++) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue