Merge pull request #16431 from sabrina-shanman/instancing_slimmesh

(DEV-564) Introduce and populate geometry-only mesh representation from hfm::Mesh
This commit is contained in:
Sam Gateau 2019-10-31 15:08:52 -07:00 committed by GitHub
commit ad0fce9c3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 118 additions and 9 deletions

View file

@ -229,6 +229,14 @@ public:
bool needTangentSpace() const;
};
/// Simple Triangle List Mesh
struct TriangleListMesh {
std::vector<glm::vec3> vertices;
std::vector<uint32_t> indices;
std::vector<glm::ivec2> parts; // Offset in the indices, Number of indices
};
/// A single mesh (with optional blendshapes).
class Mesh {
public:
@ -254,12 +262,15 @@ public:
// Blendshape attributes
QVector<Blendshape> blendshapes;
// Simple Triangle List Mesh generated during baking
hfm::TriangleListMesh triangleListMesh;
QVector<int32_t> originalIndices; // Original indices of the vertices
unsigned int meshIndex; // the order the meshes appeared in the object file
graphics::MeshPointer _mesh;
bool wasCompressed { false };
};
/// A single animation frame.

View file

@ -12,7 +12,11 @@
#include "HFMModelMath.h"
#include <LogHandler.h>
#include "ModelFormatLogging.h"
#include <unordered_map>
#include <GLMHelpers.h>
#include <glm/gtx/hash.hpp>
namespace hfm {
@ -139,4 +143,60 @@ ReweightedDeformers getReweightedDeformers(const size_t numMeshVertices, const s
return reweightedDeformers;
}
const TriangleListMesh generateTriangleListMesh(const std::vector<glm::vec3>& srcVertices, const std::vector<HFMMeshPart>& srcParts) {
TriangleListMesh dest;
// copy vertices for now
dest.vertices = srcVertices;
std::vector<uint32_t> oldToNewIndex(srcVertices.size());
{
std::unordered_map<glm::vec3, uint32_t> uniqueVertexToNewIndex;
int oldIndex = 0;
int newIndex = 0;
for (const auto& srcVertex : srcVertices) {
auto foundIndex = uniqueVertexToNewIndex.find(srcVertex);
if (foundIndex != uniqueVertexToNewIndex.end()) {
oldToNewIndex[oldIndex] = foundIndex->second;
} else {
uniqueVertexToNewIndex[srcVertex] = newIndex;
oldToNewIndex[oldIndex] = newIndex;
dest.vertices[newIndex] = srcVertex;
++newIndex;
}
++oldIndex;
}
if (uniqueVertexToNewIndex.size() < srcVertices.size()) {
dest.vertices.resize(uniqueVertexToNewIndex.size());
dest.vertices.shrink_to_fit();
}
}
auto newIndicesCount = 0;
for (const auto& part : srcParts) {
newIndicesCount += part.triangleIndices.size() + part.quadTrianglesIndices.size();
}
{
dest.indices.resize(newIndicesCount);
int i = 0;
for (const auto& part : srcParts) {
glm::ivec2 spart(i, 0);
for (const auto& qti : part.quadTrianglesIndices) {
dest.indices[i] = oldToNewIndex[qti];
++i;
}
for (const auto& ti : part.triangleIndices) {
dest.indices[i] = oldToNewIndex[ti];
++i;
}
spart.y = i - spart.x;
dest.parts.push_back(spart);
}
}
return dest;
}
};

View file

@ -25,8 +25,7 @@ void calculateExtentsForShape(hfm::Shape& shape, const std::vector<hfm::Mesh>& m
void calculateExtentsForModel(Extents& modelExtents, const std::vector<hfm::Shape>& shapes);
class ReweightedDeformers {
public:
struct ReweightedDeformers {
std::vector<uint16_t> indices;
std::vector<uint16_t> weights;
uint16_t weightsPerVertex { 0 };
@ -36,6 +35,9 @@ public:
const uint16_t DEFAULT_SKINNING_WEIGHTS_PER_VERTEX = 4;
ReweightedDeformers getReweightedDeformers(const size_t numMeshVertices, const std::vector<hfm::SkinCluster> skinClusters, const uint16_t weightsPerVertex = DEFAULT_SKINNING_WEIGHTS_PER_VERTEX);
const TriangleListMesh generateTriangleListMesh(const std::vector<glm::vec3>& srcVertices, const std::vector<HFMMeshPart>& srcParts);
};
#endif // #define hifi_hfm_ModelMath_h

View file

@ -23,6 +23,7 @@
#include "CalculateExtentsTask.h"
#include "BuildDracoMeshTask.h"
#include "ParseFlowDataTask.h"
#include <hfm/HFMModelMath.h>
namespace baker {
@ -49,6 +50,26 @@ namespace baker {
}
};
class BuildMeshTriangleListTask {
public:
using Input = std::vector<hfm::Mesh>;
using Output = std::vector<hfm::TriangleListMesh>;
using JobModel = Job::ModelIO<BuildMeshTriangleListTask, Input, Output>;
void run(const BakeContextPointer& context, const Input& input, Output& output) {
const auto& meshesIn = input;
auto& indexedTrianglesMeshOut = output;
indexedTrianglesMeshOut.clear();
indexedTrianglesMeshOut.resize(meshesIn.size());
for (size_t i = 0; i < meshesIn.size(); i++) {
auto& mesh = meshesIn[i];
const auto verticesStd = mesh.vertices.toStdVector();
indexedTrianglesMeshOut[i] = hfm::generateTriangleListMesh(verticesStd, mesh.parts);
}
}
};
class BuildBlendshapesTask {
public:
using Input = VaryingSet3<BlendshapesPerMesh, std::vector<NormalsPerBlendshape>, std::vector<TangentsPerBlendshape>>;
@ -80,21 +101,23 @@ namespace baker {
class BuildMeshesTask {
public:
using Input = VaryingSet5<std::vector<hfm::Mesh>, std::vector<graphics::MeshPointer>, NormalsPerMesh, TangentsPerMesh, BlendshapesPerMesh>;
using Input = VaryingSet6<std::vector<hfm::Mesh>, std::vector<hfm::TriangleListMesh>, std::vector<graphics::MeshPointer>, NormalsPerMesh, TangentsPerMesh, BlendshapesPerMesh>;
using Output = std::vector<hfm::Mesh>;
using JobModel = Job::ModelIO<BuildMeshesTask, Input, Output>;
void run(const BakeContextPointer& context, const Input& input, Output& output) {
auto& meshesIn = input.get0();
int numMeshes = (int)meshesIn.size();
auto& graphicsMeshesIn = input.get1();
auto& normalsPerMeshIn = input.get2();
auto& tangentsPerMeshIn = input.get3();
auto& blendshapesPerMeshIn = input.get4();
auto& triangleListMeshesIn = input.get1();
auto& graphicsMeshesIn = input.get2();
auto& normalsPerMeshIn = input.get3();
auto& tangentsPerMeshIn = input.get4();
auto& blendshapesPerMeshIn = input.get5();
auto meshesOut = meshesIn;
for (int i = 0; i < numMeshes; i++) {
auto& meshOut = meshesOut[i];
meshOut.triangleListMesh = triangleListMeshesIn[i];
meshOut._mesh = safeGet(graphicsMeshesIn, i);
meshOut.normals = QVector<glm::vec3>::fromStdVector(safeGet(normalsPerMeshIn, i));
meshOut.tangents = QVector<glm::vec3>::fromStdVector(safeGet(tangentsPerMeshIn, i));
@ -162,6 +185,9 @@ namespace baker {
const auto collectShapeVerticesInputs = CollectShapeVerticesTask::Input(meshesIn, shapesIn, jointsIn, skinDeformersIn).asVarying();
const auto shapeVerticesPerJoint = model.addJob<CollectShapeVerticesTask>("CollectShapeVertices", collectShapeVerticesInputs);
// Build the slim triangle list mesh for each hfm::mesh
const auto triangleListMeshes = model.addJob<BuildMeshTriangleListTask>("BuildMeshTriangleListTask", meshesIn);
// Build the graphics::MeshPointer for each hfm::Mesh
const auto buildGraphicsMeshInputs = BuildGraphicsMeshTask::Input(meshesIn, url, meshIndicesToModelNames, normalsPerMesh, tangentsPerMesh, shapesIn, skinDeformersIn).asVarying();
const auto graphicsMeshes = model.addJob<BuildGraphicsMeshTask>("BuildGraphicsMesh", buildGraphicsMeshInputs);
@ -200,7 +226,7 @@ namespace baker {
// Combine the outputs into a new hfm::Model
const auto buildBlendshapesInputs = BuildBlendshapesTask::Input(blendshapesPerMeshIn, normalsPerBlendshapePerMesh, tangentsPerBlendshapePerMesh).asVarying();
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, triangleListMeshes, graphicsMeshes, normalsPerMesh, tangentsPerMesh, blendshapesPerMeshOut).asVarying();
const auto meshesOut = model.addJob<BuildMeshesTask>("BuildMeshes", buildMeshesInputs);
const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices, flowData, shapeVerticesPerJoint, shapesOut, modelExtentsOut).asVarying();
const auto hfmModelOut = model.addJob<BuildModelTask>("BuildModel", buildModelInputs);

View file

@ -392,4 +392,14 @@ inline glm::vec4 extractFov( const glm::mat4& m) {
return result;
}
inline bool operator<(const glm::vec3& lhs, const glm::vec3& rhs) {
return (lhs.x < rhs.x) || (
(lhs.x == rhs.x) && (
(lhs.y < rhs.y) || (
(lhs.y == rhs.y) && (lhs.z < rhs.z)
)
)
);
}
#endif // hifi_GLMHelpers_h