mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-07 10:02:24 +02:00
Add CollectShapeVerticesTask
This commit is contained in:
parent
2077da6f37
commit
cd94dc15f9
3 changed files with 131 additions and 2 deletions
|
@ -14,6 +14,7 @@
|
|||
#include "BakerTypes.h"
|
||||
#include "ModelMath.h"
|
||||
#include "ReweightDeformersTask.h"
|
||||
#include "CollectShapeVerticesTask.h"
|
||||
#include "BuildGraphicsMeshTask.h"
|
||||
#include "CalculateMeshNormalsTask.h"
|
||||
#include "CalculateMeshTangentsTask.h"
|
||||
|
@ -105,7 +106,7 @@ namespace baker {
|
|||
|
||||
class BuildModelTask {
|
||||
public:
|
||||
using Input = VaryingSet6<hfm::Model::Pointer, std::vector<hfm::Mesh>, std::vector<hfm::Joint>, QMap<int, glm::quat>, QHash<QString, int>, FlowData>;
|
||||
using Input = VaryingSet7<hfm::Model::Pointer, std::vector<hfm::Mesh>, std::vector<hfm::Joint>, QMap<int, glm::quat>, QHash<QString, int>, FlowData, std::vector<ShapeVertices>>;
|
||||
using Output = hfm::Model::Pointer;
|
||||
using JobModel = Job::ModelIO<BuildModelTask, Input, Output>;
|
||||
|
||||
|
@ -116,6 +117,9 @@ namespace baker {
|
|||
hfmModelOut->jointRotationOffsets = input.get3();
|
||||
hfmModelOut->jointIndices = input.get4();
|
||||
hfmModelOut->flowData = input.get5();
|
||||
hfmModelOut->shapeVertices = input.get6();
|
||||
// These depend on the ShapeVertices
|
||||
// TODO: Create a task for this rather than calculating it here
|
||||
hfmModelOut->computeKdops();
|
||||
output = hfmModelOut;
|
||||
}
|
||||
|
@ -156,6 +160,9 @@ namespace baker {
|
|||
// 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 reweightedDeformers = model.addJob<ReweightDeformersTask>("ReweightDeformers", reweightDeformersInputs);
|
||||
// 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 shapeVerticesPerJoint = model.addJob<CollectShapeVerticesTask>("CollectShapeVertices", collectShapeVerticesInputs);
|
||||
|
||||
// Build the graphics::MeshPointer for each hfm::Mesh
|
||||
const auto buildGraphicsMeshInputs = BuildGraphicsMeshTask::Input(meshesIn, url, meshIndicesToModelNames, normalsPerMesh, tangentsPerMesh, shapesIn, dynamicTransformsIn, reweightedDeformers).asVarying();
|
||||
|
@ -191,7 +198,7 @@ namespace baker {
|
|||
const auto blendshapesPerMeshOut = model.addJob<BuildBlendshapesTask>("BuildBlendshapes", buildBlendshapesInputs);
|
||||
const auto buildMeshesInputs = BuildMeshesTask::Input(meshesIn, graphicsMeshes, normalsPerMesh, tangentsPerMesh, blendshapesPerMeshOut).asVarying();
|
||||
const auto meshesOut = model.addJob<BuildMeshesTask>("BuildMeshes", buildMeshesInputs);
|
||||
const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices, flowData).asVarying();
|
||||
const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices, flowData, shapeVerticesPerJoint).asVarying();
|
||||
const auto hfmModelOut = model.addJob<BuildModelTask>("BuildModel", buildModelInputs);
|
||||
|
||||
output = Output(hfmModelOut, materialMapping, dracoMeshes, dracoErrors, materialList);
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
//
|
||||
// CollectShapeVerticesTask.h
|
||||
// model-baker/src/model-baker
|
||||
//
|
||||
// Created by Sabrina Shanman on 2019/09/27.
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "CollectShapeVerticesTask.h"
|
||||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
// Used to track and avoid duplicate shape vertices, as multiple shapes can have the same mesh and dynamicTransform
|
||||
class VertexSource {
|
||||
public:
|
||||
uint32_t mesh;
|
||||
uint32_t dynamicTransform;
|
||||
|
||||
bool operator==(const VertexSource& other) const {
|
||||
return mesh == other.mesh &&
|
||||
dynamicTransform == other.dynamicTransform;
|
||||
}
|
||||
};
|
||||
|
||||
void CollectShapeVerticesTask::run(const baker::BakeContextPointer& context, const Input& input, Output& output) {
|
||||
const auto& meshes = input.get0();
|
||||
const auto& shapes = input.get1();
|
||||
const auto& joints = input.get2();
|
||||
const auto& dynamicTransforms = input.get3();
|
||||
const auto& reweightedDeformers = input.get4();
|
||||
auto& shapeVerticesPerJoint = output;
|
||||
|
||||
shapeVerticesPerJoint.reserve(joints.size());
|
||||
std::vector<std::vector<VertexSource>> vertexSourcesPerJoint;
|
||||
vertexSourcesPerJoint.resize(joints.size());
|
||||
for (size_t i = 0; i < shapes.size(); ++i) {
|
||||
const auto& shape = shapes[i];
|
||||
const uint32_t dynamicTransformKey = shape.dynamicTransform;
|
||||
if (dynamicTransformKey == hfm::UNDEFINED_KEY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
VertexSource vertexSource;
|
||||
vertexSource.mesh = shape.mesh;
|
||||
vertexSource.dynamicTransform = dynamicTransformKey;
|
||||
|
||||
const auto& dynamicTransform = dynamicTransforms[dynamicTransformKey];
|
||||
for (size_t j = 0; j < dynamicTransform.clusters.size(); ++j) {
|
||||
const auto& cluster = dynamicTransform.clusters[j];
|
||||
const uint32_t jointIndex = cluster.jointIndex;
|
||||
|
||||
auto& vertexSources = vertexSourcesPerJoint[jointIndex];
|
||||
if (std::find(vertexSources.cbegin(), vertexSources.cend(), vertexSource) == vertexSources.cend()) {
|
||||
vertexSources.push_back(vertexSource);
|
||||
auto& shapeVertices = shapeVerticesPerJoint[jointIndex];
|
||||
|
||||
const uint16_t deformerIndex = dynamicTransform.deformers[j];
|
||||
const auto& mesh = meshes[shape.mesh];
|
||||
const auto& vertices = mesh.vertices;
|
||||
const auto& reweightedDeformer = reweightedDeformers[shape.mesh];
|
||||
const glm::mat4 meshToJoint = cluster.inverseBindMatrix;
|
||||
|
||||
const uint16_t weightsPerVertex = reweightedDeformer.weightsPerVertex;
|
||||
if (weightsPerVertex == 0) {
|
||||
for (int vertexIndex = 0; vertexIndex < (int)vertices.size(); ++vertexIndex) {
|
||||
const glm::mat4 vertexTransform = meshToJoint * glm::translate(vertices[vertexIndex]);
|
||||
shapeVertices.push_back(extractTranslation(vertexTransform));
|
||||
}
|
||||
} else {
|
||||
for (int vertexIndex = 0; vertexIndex < (int)vertices.size(); ++vertexIndex) {
|
||||
for (uint16_t weightIndex = 0; weightIndex < weightsPerVertex; ++weightIndex) {
|
||||
const size_t index = vertexIndex*4 + weightIndex;
|
||||
const uint16_t clusterIndex = reweightedDeformer.indices[index];
|
||||
const uint16_t clusterWeight = reweightedDeformer.weights[index];
|
||||
// Remember vertices associated with this joint with at least 1/4 weight
|
||||
const uint16_t EXPANSION_WEIGHT_THRESHOLD = std::numeric_limits<uint16_t>::max() / 4;
|
||||
if (clusterIndex != j || clusterWeight < EXPANSION_WEIGHT_THRESHOLD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const glm::mat4 vertexTransform = meshToJoint * glm::translate(vertices[vertexIndex]);
|
||||
shapeVertices.push_back(extractTranslation(vertexTransform));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// CollectShapeVerticesTask.h
|
||||
// model-baker/src/model-baker
|
||||
//
|
||||
// Created by Sabrina Shanman on 2019/09/27.
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_CollectShapeVerticesTask_h
|
||||
#define hifi_CollectShapeVerticesTask_h
|
||||
|
||||
#include <hfm/HFM.h>
|
||||
|
||||
#include "Engine.h"
|
||||
#include "BakerTypes.h"
|
||||
|
||||
class CollectShapeVerticesTask {
|
||||
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 Output = std::vector<ShapeVertices>;
|
||||
using JobModel = baker::Job::ModelIO<CollectShapeVerticesTask, Input, Output>;
|
||||
|
||||
void run(const baker::BakeContextPointer& context, const Input& input, Output& output);
|
||||
};
|
||||
|
||||
#endif // hifi_CollectShapeVerticesTask_h
|
||||
|
Loading…
Reference in a new issue