mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 22:28:37 +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 "BakerTypes.h"
|
||||||
#include "ModelMath.h"
|
#include "ModelMath.h"
|
||||||
#include "ReweightDeformersTask.h"
|
#include "ReweightDeformersTask.h"
|
||||||
|
#include "CollectShapeVerticesTask.h"
|
||||||
#include "BuildGraphicsMeshTask.h"
|
#include "BuildGraphicsMeshTask.h"
|
||||||
#include "CalculateMeshNormalsTask.h"
|
#include "CalculateMeshNormalsTask.h"
|
||||||
#include "CalculateMeshTangentsTask.h"
|
#include "CalculateMeshTangentsTask.h"
|
||||||
|
@ -105,7 +106,7 @@ namespace baker {
|
||||||
|
|
||||||
class BuildModelTask {
|
class BuildModelTask {
|
||||||
public:
|
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 Output = hfm::Model::Pointer;
|
||||||
using JobModel = Job::ModelIO<BuildModelTask, Input, Output>;
|
using JobModel = Job::ModelIO<BuildModelTask, Input, Output>;
|
||||||
|
|
||||||
|
@ -116,6 +117,9 @@ namespace baker {
|
||||||
hfmModelOut->jointRotationOffsets = input.get3();
|
hfmModelOut->jointRotationOffsets = input.get3();
|
||||||
hfmModelOut->jointIndices = input.get4();
|
hfmModelOut->jointIndices = input.get4();
|
||||||
hfmModelOut->flowData = input.get5();
|
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();
|
hfmModelOut->computeKdops();
|
||||||
output = hfmModelOut;
|
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.
|
// 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, dynamicTransformsIn, 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.
|
||||||
|
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
|
// 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, dynamicTransformsIn, reweightedDeformers).asVarying();
|
||||||
|
@ -191,7 +198,7 @@ namespace baker {
|
||||||
const auto blendshapesPerMeshOut = model.addJob<BuildBlendshapesTask>("BuildBlendshapes", buildBlendshapesInputs);
|
const auto blendshapesPerMeshOut = model.addJob<BuildBlendshapesTask>("BuildBlendshapes", buildBlendshapesInputs);
|
||||||
const auto buildMeshesInputs = BuildMeshesTask::Input(meshesIn, graphicsMeshes, normalsPerMesh, tangentsPerMesh, blendshapesPerMeshOut).asVarying();
|
const auto buildMeshesInputs = BuildMeshesTask::Input(meshesIn, graphicsMeshes, normalsPerMesh, tangentsPerMesh, blendshapesPerMeshOut).asVarying();
|
||||||
const auto meshesOut = model.addJob<BuildMeshesTask>("BuildMeshes", buildMeshesInputs);
|
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);
|
const auto hfmModelOut = model.addJob<BuildModelTask>("BuildModel", buildModelInputs);
|
||||||
|
|
||||||
output = Output(hfmModelOut, materialMapping, dracoMeshes, dracoErrors, materialList);
|
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