FBX2glTF/src/fbx/FbxBlendShapesAccess.cpp

73 lines
2.7 KiB
C++

/**
* Copyright (c) Facebook, Inc. and its affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "FbxBlendShapesAccess.hpp"
FbxBlendShapesAccess::TargetShape::TargetShape(const FbxShape* shape, FbxDouble fullWeight)
: shape(shape),
fullWeight(fullWeight),
count(shape->GetControlPointsCount()),
positions(shape->GetControlPoints()),
normals(FbxLayerElementAccess<FbxVector4>(
shape->GetElementNormal(),
shape->GetElementNormalCount())),
tangents(FbxLayerElementAccess<FbxVector4>(
shape->GetElementTangent(),
shape->GetElementTangentCount())) {}
FbxAnimCurve* FbxBlendShapesAccess::BlendChannel::ExtractAnimation(unsigned int animIx) const {
FbxAnimStack* stack = mesh->GetScene()->GetSrcObject<FbxAnimStack>(animIx);
FbxAnimLayer* layer = stack->GetMember<FbxAnimLayer>(0);
return mesh->GetShapeChannel(blendShapeIx, channelIx, layer, true);
}
FbxBlendShapesAccess::BlendChannel::BlendChannel(
FbxMesh* mesh,
const unsigned int blendShapeIx,
const unsigned int channelIx,
const FbxDouble deformPercent,
const std::vector<FbxBlendShapesAccess::TargetShape>& targetShapes,
std::string name)
: mesh(mesh),
blendShapeIx(blendShapeIx),
channelIx(channelIx),
deformPercent(deformPercent),
targetShapes(targetShapes),
name(name) {}
std::vector<FbxBlendShapesAccess::BlendChannel> FbxBlendShapesAccess::extractChannels(
FbxMesh* mesh) const {
std::vector<BlendChannel> channels;
for (int shapeIx = 0; shapeIx < mesh->GetDeformerCount(FbxDeformer::eBlendShape); shapeIx++) {
auto* fbxBlendShape =
static_cast<FbxBlendShape*>(mesh->GetDeformer(shapeIx, FbxDeformer::eBlendShape));
for (int channelIx = 0; channelIx < fbxBlendShape->GetBlendShapeChannelCount(); ++channelIx) {
FbxBlendShapeChannel* fbxChannel = fbxBlendShape->GetBlendShapeChannel(channelIx);
if (fbxChannel->GetTargetShapeCount() > 0) {
std::vector<TargetShape> targetShapes;
const double* fullWeights = fbxChannel->GetTargetShapeFullWeights();
std::string name = std::string(fbxChannel->GetName());
if (verboseOutput) {
fmt::printf("\rblendshape channel: %s\n", name);
}
for (int targetIx = 0; targetIx < fbxChannel->GetTargetShapeCount(); targetIx++) {
FbxShape* fbxShape = fbxChannel->GetTargetShape(targetIx);
targetShapes.emplace_back(fbxShape, fullWeights[targetIx]);
}
channels.emplace_back(
mesh, shapeIx, channelIx, fbxChannel->DeformPercent * 0.01, targetShapes, name);
}
}
}
return channels;
}