mirror of
https://github.com/overte-org/overte.git
synced 2025-07-15 20:36:48 +02:00
Dual Quaternion skinning optimization
Reduce expensive conversion from quat -> matrix -> quat, by keeping the inverseBindPose in a Transform instance instead of a mat4.
This commit is contained in:
parent
aacf2d489f
commit
b8c88fca3b
5 changed files with 33 additions and 19 deletions
|
@ -115,6 +115,7 @@ public:
|
||||||
|
|
||||||
int jointIndex;
|
int jointIndex;
|
||||||
glm::mat4 inverseBindMatrix;
|
glm::mat4 inverseBindMatrix;
|
||||||
|
Transform inverseBindTransform;
|
||||||
};
|
};
|
||||||
|
|
||||||
const int MAX_NUM_PIXELS_FOR_FBX_TEXTURE = 2048 * 2048;
|
const int MAX_NUM_PIXELS_FOR_FBX_TEXTURE = 2048 * 2048;
|
||||||
|
|
|
@ -1613,6 +1613,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
|
||||||
fbxCluster.jointIndex = 0;
|
fbxCluster.jointIndex = 0;
|
||||||
}
|
}
|
||||||
fbxCluster.inverseBindMatrix = glm::inverse(cluster.transformLink) * modelTransform;
|
fbxCluster.inverseBindMatrix = glm::inverse(cluster.transformLink) * modelTransform;
|
||||||
|
fbxCluster.inverseBindTransform = Transform(fbxCluster.inverseBindMatrix);
|
||||||
extracted.mesh.clusters.append(fbxCluster);
|
extracted.mesh.clusters.append(fbxCluster);
|
||||||
|
|
||||||
// override the bind rotation with the transform link
|
// override the bind rotation with the transform link
|
||||||
|
|
|
@ -109,13 +109,14 @@ void CauterizedModel::updateClusterMatrices() {
|
||||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||||
|
|
||||||
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
|
||||||
#if defined(SKIN_DQ)
|
#if defined(SKIN_DQ)
|
||||||
glm::mat4 m;
|
auto jointPose = _rig.getJointPose(cluster.jointIndex);
|
||||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
|
Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans());
|
||||||
state.clusterTransforms[j] = Model::TransformDualQuaternion(m);
|
Transform clusterTransform;
|
||||||
|
Transform::mult(clusterTransform, jointTransform, cluster.inverseBindTransform);
|
||||||
|
state.clusterTransforms[j] = Model::TransformDualQuaternion(clusterTransform);
|
||||||
#else
|
#else
|
||||||
|
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
||||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
|
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -123,14 +124,17 @@ void CauterizedModel::updateClusterMatrices() {
|
||||||
|
|
||||||
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
|
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
|
||||||
if (!_cauterizeBoneSet.empty()) {
|
if (!_cauterizeBoneSet.empty()) {
|
||||||
|
#if defined(SKIN_DQ)
|
||||||
|
AnimPose cauterizePose = _rig.getJointPose(geometry.neckJointIndex);
|
||||||
|
cauterizePose.scale() = glm::vec3(0.0001f, 0.0001f, 0.0001f);
|
||||||
|
#else
|
||||||
static const glm::mat4 zeroScale(
|
static const glm::mat4 zeroScale(
|
||||||
glm::vec4(0.0001f, 0.0f, 0.0f, 0.0f),
|
glm::vec4(0.0001f, 0.0f, 0.0f, 0.0f),
|
||||||
glm::vec4(0.0f, 0.0001f, 0.0f, 0.0f),
|
glm::vec4(0.0f, 0.0001f, 0.0f, 0.0f),
|
||||||
glm::vec4(0.0f, 0.0f, 0.0001f, 0.0f),
|
glm::vec4(0.0f, 0.0f, 0.0001f, 0.0f),
|
||||||
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
auto cauterizeMatrix = _rig.getJointTransform(geometry.neckJointIndex) * zeroScale;
|
auto cauterizeMatrix = _rig.getJointTransform(geometry.neckJointIndex) * zeroScale;
|
||||||
|
#endif
|
||||||
for (int i = 0; i < _cauterizeMeshStates.size(); i++) {
|
for (int i = 0; i < _cauterizeMeshStates.size(); i++) {
|
||||||
Model::MeshState& state = _cauterizeMeshStates[i];
|
Model::MeshState& state = _cauterizeMeshStates[i];
|
||||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||||
|
@ -138,18 +142,19 @@ void CauterizedModel::updateClusterMatrices() {
|
||||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||||
|
|
||||||
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
if (_cauterizeBoneSet.find(cluster.jointIndex) == _cauterizeBoneSet.end()) {
|
||||||
if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) {
|
// not cauterized so just copy the value from the non-cauterized version.
|
||||||
jointMatrix = cauterizeMatrix;
|
state.clusterTransforms[j] = _meshStates[i].clusterTransforms[j];
|
||||||
}
|
} else {
|
||||||
|
|
||||||
#if defined(SKIN_DQ)
|
#if defined(SKIN_DQ)
|
||||||
glm::mat4 m;
|
Transform jointTransform(cauterizePose.rot(), cauterizePose.scale(), cauterizePose.trans());
|
||||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
|
Transform clusterTransform;
|
||||||
state.clusterTransforms[j] = Model::TransformDualQuaternion(m);
|
Transform::mult(clusterTransform, jointTransform, cluster.inverseBindTransform);
|
||||||
|
state.clusterTransforms[j] = Model::TransformDualQuaternion(clusterTransform);
|
||||||
#else
|
#else
|
||||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
|
glm_mat4u_mul(cauterizeMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1188,10 +1188,13 @@ void Model::updateClusterMatrices() {
|
||||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||||
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
||||||
#if defined(SKIN_DQ)
|
#if defined(SKIN_DQ)
|
||||||
glm::mat4 mat;
|
auto jointPose = _rig.getJointPose(cluster.jointIndex);
|
||||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, mat);
|
Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans());
|
||||||
state.clusterTransforms[j] = TransformDualQuaternion(mat);
|
Transform clusterTransform;
|
||||||
|
Transform::mult(clusterTransform, jointTransform, cluster.inverseBindTransform);
|
||||||
|
state.clusterTransforms[j] = Model::TransformDualQuaternion(clusterTransform);
|
||||||
#else
|
#else
|
||||||
|
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
||||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
|
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -268,6 +268,10 @@ public:
|
||||||
_scale.z = scale.z;
|
_scale.z = scale.z;
|
||||||
_dq = DualQuaternion(rot, trans);
|
_dq = DualQuaternion(rot, trans);
|
||||||
}
|
}
|
||||||
|
TransformDualQuaternion(const Transform& transform) {
|
||||||
|
_scale = glm::vec4(transform.getScale(), 0.0f);
|
||||||
|
_dq = DualQuaternion(transform.getRotation(), transform.getTranslation());
|
||||||
|
}
|
||||||
glm::vec3 getScale() const { return glm::vec3(_scale); }
|
glm::vec3 getScale() const { return glm::vec3(_scale); }
|
||||||
glm::quat getRotation() const { return _dq.getRotation(); }
|
glm::quat getRotation() const { return _dq.getRotation(); }
|
||||||
glm::vec3 getTranslation() const { return _dq.getTranslation(); }
|
glm::vec3 getTranslation() const { return _dq.getTranslation(); }
|
||||||
|
|
Loading…
Reference in a new issue