Drop 0-100 assumptions. Let influences go wild.
This commit is contained in:
parent
ec303a3b8a
commit
9520c26649
|
@ -470,11 +470,8 @@ private:
|
||||||
class FbxBlendShapesAccess
|
class FbxBlendShapesAccess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct BlendChannel {
|
struct TargetShape
|
||||||
explicit BlendChannel(FbxDouble defaultDeform) :
|
{
|
||||||
defaultDeform(defaultDeform)
|
|
||||||
{}
|
|
||||||
struct TargetShape {
|
|
||||||
TargetShape(
|
TargetShape(
|
||||||
double fullWeight,
|
double fullWeight,
|
||||||
const std::vector<FbxVector4> &positions,
|
const std::vector<FbxVector4> &positions,
|
||||||
|
@ -483,8 +480,7 @@ public:
|
||||||
) : fullWeight(fullWeight),
|
) : fullWeight(fullWeight),
|
||||||
positions(positions),
|
positions(positions),
|
||||||
normals(normals),
|
normals(normals),
|
||||||
tangents(tangents)
|
tangents(tangents) {}
|
||||||
{}
|
|
||||||
|
|
||||||
const double fullWeight;
|
const double fullWeight;
|
||||||
const std::vector<FbxVector4> positions;
|
const std::vector<FbxVector4> positions;
|
||||||
|
@ -492,6 +488,10 @@ public:
|
||||||
const std::vector<FbxVector4> tangents;
|
const std::vector<FbxVector4> tangents;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BlendChannel {
|
||||||
|
explicit BlendChannel(FbxDouble defaultDeform) :
|
||||||
|
defaultDeform(defaultDeform)
|
||||||
|
{}
|
||||||
const FbxDouble defaultDeform;
|
const FbxDouble defaultDeform;
|
||||||
|
|
||||||
// one for each FbxShape
|
// one for each FbxShape
|
||||||
|
@ -510,7 +510,7 @@ public:
|
||||||
return channels.at(channelIx).defaultDeform;
|
return channels.at(channelIx).defaultDeform;
|
||||||
}
|
}
|
||||||
size_t GetTargetShapeCount(size_t channelIx) const { return channels[channelIx].targetShapes.size(); }
|
size_t GetTargetShapeCount(size_t channelIx) const { return channels[channelIx].targetShapes.size(); }
|
||||||
const BlendChannel::TargetShape &GetTargetShape(size_t channelIx, size_t targetShapeIx) const {
|
const TargetShape &GetTargetShape(size_t channelIx, size_t targetShapeIx) const {
|
||||||
return channels.at(channelIx).targetShapes[targetShapeIx];
|
return channels.at(channelIx).targetShapes[targetShapeIx];
|
||||||
}
|
}
|
||||||
size_t GetAnimCount(size_t channelIx) const { return channels.at(channelIx).animations.size(); }
|
size_t GetAnimCount(size_t channelIx) const { return channels.at(channelIx).animations.size(); }
|
||||||
|
@ -589,7 +589,7 @@ private:
|
||||||
#endif
|
#endif
|
||||||
// finally combine all this into a TargetShape and add it to our work-in-progress BlendChannel
|
// finally combine all this into a TargetShape and add it to our work-in-progress BlendChannel
|
||||||
shape.targetShapes.push_back(
|
shape.targetShapes.push_back(
|
||||||
BlendChannel::TargetShape(fullWeights[targetShapeIx], positions, normals, tangents)
|
TargetShape(fullWeights[targetShapeIx], positions, normals, tangents)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,12 +712,14 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std:
|
||||||
}
|
}
|
||||||
|
|
||||||
rawSurface.blendChannels.clear();
|
rawSurface.blendChannels.clear();
|
||||||
|
std::vector<const FbxBlendShapesAccess::TargetShape *> targetShapes;
|
||||||
for (size_t shapeIx = 0; shapeIx < blendShapes.GetChannelCount(); shapeIx ++) {
|
for (size_t shapeIx = 0; shapeIx < blendShapes.GetChannelCount(); shapeIx ++) {
|
||||||
for (size_t targetIx = 0; targetIx < blendShapes.GetTargetShapeCount(shapeIx); targetIx ++) {
|
for (size_t targetIx = 0; targetIx < blendShapes.GetTargetShapeCount(shapeIx); targetIx ++) {
|
||||||
const auto &shape = blendShapes.GetTargetShape(shapeIx, targetIx);
|
const FbxBlendShapesAccess::TargetShape &shape = blendShapes.GetTargetShape(shapeIx, targetIx);
|
||||||
float defaultDeform = static_cast<float>(blendShapes.GetDefaultDeform(shapeIx));
|
targetShapes.push_back(&shape);
|
||||||
|
|
||||||
rawSurface.blendChannels.push_back(RawBlendChannel {
|
rawSurface.blendChannels.push_back(RawBlendChannel {
|
||||||
defaultDeform,
|
static_cast<float>(blendShapes.GetDefaultDeform(shapeIx)),
|
||||||
!shape.normals.empty(),
|
!shape.normals.empty(),
|
||||||
!shape.tangents.empty()
|
!shape.tangents.empty()
|
||||||
});
|
});
|
||||||
|
@ -824,21 +826,22 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std:
|
||||||
|
|
||||||
rawSurface.bounds.AddPoint(vertex.position);
|
rawSurface.bounds.AddPoint(vertex.position);
|
||||||
|
|
||||||
for (size_t shapeIx = 0; shapeIx < blendShapes.GetChannelCount(); shapeIx ++) {
|
if (!targetShapes.empty()) {
|
||||||
for (size_t targetIx = 0; targetIx < blendShapes.GetTargetShapeCount(shapeIx); targetIx ++) {
|
vertex.blendSurfaceIx = rawSurfaceIndex;
|
||||||
const auto &shape = blendShapes.GetTargetShape(shapeIx, targetIx);
|
for (const auto *targetShape : targetShapes) {
|
||||||
|
|
||||||
RawBlendVertex blendVertex;
|
RawBlendVertex blendVertex;
|
||||||
// the morph target positions must be transformed just as with the vertex positions above
|
// the morph target positions must be transformed just as with the vertex positions above
|
||||||
blendVertex.position = toVec3(transform.MultNormalize(shape.positions[controlPointIndex]));
|
blendVertex.position = toVec3f(transform.MultNormalize(targetShape->positions[controlPointIndex]));
|
||||||
if (!shape.normals.empty()) {
|
if (!targetShape->normals.empty()) {
|
||||||
blendVertex.normal = toVec3(shape.normals[controlPointIndex]);
|
blendVertex.normal = toVec3f(targetShape->normals[controlPointIndex]);
|
||||||
}
|
}
|
||||||
if (!shape.tangents.empty()) {
|
if (!targetShape->tangents.empty()) {
|
||||||
blendVertex.tangent = toVec4(shape.tangents[controlPointIndex]);
|
blendVertex.tangent = toVec4f(targetShape->tangents[controlPointIndex]);
|
||||||
}
|
}
|
||||||
vertex.blends.push_back(blendVertex);
|
vertex.blends.push_back(blendVertex);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
vertex.blendSurfaceIx = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skinning.IsSkinned()) {
|
if (skinning.IsSkinned()) {
|
||||||
|
@ -1138,20 +1141,25 @@ static void ReadAnimations(RawModel &raw, FbxScene *pScene)
|
||||||
// the target shape 'fullWeight' values are a strictly ascending list of floats (between
|
// the target shape 'fullWeight' values are a strictly ascending list of floats (between
|
||||||
// 0 and 100), forming a sequence of intervals -- this convenience function figures out if
|
// 0 and 100), forming a sequence of intervals -- this convenience function figures out if
|
||||||
// 'p' lays between some certain target fullWeights, and if so where (from 0 to 1).
|
// 'p' lays between some certain target fullWeights, and if so where (from 0 to 1).
|
||||||
auto findInInterval = [&](double p, int n) {
|
auto findInInterval = [&](const double p, const int n) {
|
||||||
if (n >= targetCount) {
|
if (n >= targetCount) {
|
||||||
// p is certainly completely left of this interval
|
// p is certainly completely left of this interval
|
||||||
return NAN;
|
return NAN;
|
||||||
}
|
}
|
||||||
double leftWeight = (n >= 0) ? blendShapes.GetTargetShape(channelIx, n).fullWeight : 0;
|
double leftWeight = 0;
|
||||||
|
if (n >= 0) {
|
||||||
|
leftWeight = blendShapes.GetTargetShape(channelIx, n).fullWeight;
|
||||||
if (p < leftWeight) {
|
if (p < leftWeight) {
|
||||||
return NAN;
|
return NAN;
|
||||||
}
|
}
|
||||||
double rightWeight = (n < targetCount-1) ? blendShapes.GetTargetShape(channelIx, n+1).fullWeight : 100;
|
// the first interval implicitly includes all lesser influence values
|
||||||
if (p > rightWeight) {
|
|
||||||
return NAN;
|
|
||||||
}
|
}
|
||||||
// at this point leftWeight <= p <= rightWeight, return [0, 1]
|
double rightWeight = blendShapes.GetTargetShape(channelIx, n+1).fullWeight;
|
||||||
|
if (p > rightWeight && n+1 < targetCount-1) {
|
||||||
|
return NAN;
|
||||||
|
// the last interval implicitly includes all greater influence values
|
||||||
|
}
|
||||||
|
// transform p linearly such that [leftWeight, rightWeight] => [0, 1]
|
||||||
return static_cast<float>((p - leftWeight) / (rightWeight - leftWeight));
|
return static_cast<float>((p - leftWeight) / (rightWeight - leftWeight));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ bool RawVertex::operator==(const RawVertex &other) const
|
||||||
(jointIndices == other.jointIndices) &&
|
(jointIndices == other.jointIndices) &&
|
||||||
(jointWeights == other.jointWeights) &&
|
(jointWeights == other.jointWeights) &&
|
||||||
(polarityUv0 == other.polarityUv0) &&
|
(polarityUv0 == other.polarityUv0) &&
|
||||||
|
(blendSurfaceIx == other.blendSurfaceIx) &&
|
||||||
(blends == other.blends);
|
(blends == other.blends);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,9 +58,11 @@ struct RawVertex
|
||||||
Vec2f uv1 { 0.0f };
|
Vec2f uv1 { 0.0f };
|
||||||
Vec4i jointIndices { 0, 0, 0, 0 };
|
Vec4i jointIndices { 0, 0, 0, 0 };
|
||||||
Vec4f jointWeights { 0.0f };
|
Vec4f jointWeights { 0.0f };
|
||||||
|
// end of members that directly correspond to vertex attributes
|
||||||
|
|
||||||
// each vertex can have many alternate positions, normals and tangents -- one set per blend shape target.
|
// if this vertex participates in a blend shape setup, the surfaceIx of its dedicated mesh; otherwise, -1
|
||||||
// the size of this vector is always identical to the size of RawSurface.blendChannels
|
int blendSurfaceIx = -1;
|
||||||
|
// the size of this vector is always identical to the size of the corresponding RawSurface.blendChannels
|
||||||
std::vector<RawBlendVertex> blends { };
|
std::vector<RawBlendVertex> blends { };
|
||||||
|
|
||||||
bool polarityUv0;
|
bool polarityUv0;
|
||||||
|
|
Loading…
Reference in New Issue