WIP: Dual Quaternion compensation for spinning the right way.

This commit is contained in:
Anthony J. Thibault 2017-12-21 18:15:30 -08:00
parent 8bdddf7211
commit 5bb0b06061
5 changed files with 104 additions and 11 deletions

View file

@ -113,7 +113,12 @@ void CauterizedModel::updateClusterMatrices() {
for (int i = 0; i < (int)_meshStates.size(); i++) {
Model::MeshState& state = _meshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i);
#if defined(SKIN_DQ)
// HACK: FOR DQ go thru reverse order!
for (int j = mesh.clusters.size() - 1; j >= 0; j--) {
#else
for (int j = 0; j < mesh.clusters.size(); j++) {
#endif
const FBXCluster& cluster = mesh.clusters.at(j);
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
@ -127,6 +132,25 @@ void CauterizedModel::updateClusterMatrices() {
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
AnimPose p(m);
state.clusterTransforms[j] = Model::TransformDualQuaternion(m);
// AJT: HACK n^2!!!! fix me, find parent clusterTransform.
int parentIndex = _rig.getJointParentIndex(cluster.jointIndex);
int parentClusterIndex = -1;
// scan for parent!
for (int ii = mesh.clusters.size() - 1; ii > j; ii--) {
if (mesh.clusters[ii].jointIndex == parentIndex) {
parentClusterIndex = ii;
break;
}
}
// ensure that we have the same polarity as our parent!
if (parentClusterIndex >= 0) {
//if (state.clusterTransforms[parentClusterIndex]._dq.dot(state.clusterTransforms[j]._dq) < 0.0f) {
if (glm::dot(state.clusterTransforms[parentClusterIndex]._dq.real(), state.clusterTransforms[j]._dq.real()) < 0.0f) {
state.clusterTransforms[j]._dq = -state.clusterTransforms[j]._dq;
}
}
#else
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
#endif
@ -146,7 +170,13 @@ void CauterizedModel::updateClusterMatrices() {
for (int i = 0; i < _cauterizeMeshStates.size(); i++) {
Model::MeshState& state = _cauterizeMeshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i);
for (int j = 0; j < mesh.clusters.size(); j++) {
#if defined(SKIN_DQ)
// HACK: FOR DQ go thru reverse order!
for (int j = mesh.clusters.size() - 1; j >= 0; j--) {
#else
for (int j = 0; j < mesh.clusters.size(); j++) {
#endif
const FBXCluster& cluster = mesh.clusters.at(j);
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
@ -164,6 +194,25 @@ void CauterizedModel::updateClusterMatrices() {
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
AnimPose p(m);
state.clusterTransforms[j] = Model::TransformDualQuaternion(m);
// AJT: HACK n^2!!!! fix me, find parent clusterTransform.
int parentIndex = _rig.getJointParentIndex(cluster.jointIndex);
int parentClusterIndex = -1;
// scan for parent!
for (int ii = mesh.clusters.size() - 1; ii > j; ii--) {
if (mesh.clusters[ii].jointIndex == parentIndex) {
parentClusterIndex = ii;
break;
}
}
// ensure that we have the same polarity as our parent!
if (parentClusterIndex >= 0) {
//if (state.clusterTransforms[parentClusterIndex]._dq.dot(state.clusterTransforms[j]._dq) < 0.0f) {
if (glm::dot(state.clusterTransforms[parentClusterIndex]._dq.real(), state.clusterTransforms[j]._dq.real()) < 0.0f) {
state.clusterTransforms[j]._dq = -state.clusterTransforms[j]._dq;
}
}
#else
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
#endif

View file

@ -313,7 +313,7 @@ public:
glm::quat getRot() const { return _dq.getRotation(); }
glm::vec3 getTrans() const { return _dq.getTranslation(); }
glm::mat4 getMatrix() const { return createMatFromScaleQuatAndPos(getScale(), getRot(), getTrans()); };
protected:
public: // AJT: TODO FIX ME.
glm::vec4 _scale { 1.0f, 1.0f, 1.0f, 0.0f };
DualQuaternion _dq;
glm::vec4 _padding;

View file

@ -43,6 +43,7 @@ void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPositio
vec3 sAccum = vec3(0.0, 0.0, 0.0);
vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 iAccum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 prevR = vec4(0.0, 0.0, 0.0, 1.0);
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
@ -52,9 +53,18 @@ void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPositio
vec4 real = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]);
vec4 imag = vec4(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2], clusterMatrix[2][3]);
float dqClusterWeight = clusterWeight;
if (i == 0) {
prevR = real;
} else {
if (dot(prevR, real) < 0) {
dqClusterWeight = -clusterWeight;
}
}
sAccum += scale * clusterWeight;
rAccum += real * clusterWeight;
iAccum += imag * clusterWeight;
rAccum += real * dqClusterWeight;
iAccum += imag * dqClusterWeight;
}
float norm = length(rAccum);
@ -100,6 +110,7 @@ void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inP
vec3 sAccum = vec3(0.0, 0.0, 0.0);
vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 iAccum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 prevR = vec4(0.0, 0.0, 0.0, 1.0);
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
@ -109,9 +120,18 @@ void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inP
vec4 real = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]);
vec4 imag = vec4(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2], clusterMatrix[2][3]);
float dqClusterWeight = clusterWeight;
if (i == 0) {
prevR = real;
} else {
if (dot(prevR, real) < 0) {
dqClusterWeight = -clusterWeight;
}
}
sAccum += scale * clusterWeight;
rAccum += real * clusterWeight;
iAccum += imag * clusterWeight;
rAccum += real * dqClusterWeight;
iAccum += imag * dqClusterWeight;
}
float norm = length(rAccum);
@ -158,6 +178,7 @@ void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, v
vec3 sAccum = vec3(0.0, 0.0, 0.0);
vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 iAccum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 prevR = vec4(0.0, 0.0, 0.0, 1.0);
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
@ -167,9 +188,18 @@ void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, v
vec4 real = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]);
vec4 imag = vec4(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2], clusterMatrix[2][3]);
float dqClusterWeight = clusterWeight;
if (i == 0) {
prevR = real;
} else {
if (dot(prevR, real) < 0) {
dqClusterWeight = -clusterWeight;
}
}
sAccum += scale * clusterWeight;
rAccum += real * clusterWeight;
iAccum += imag * clusterWeight;
rAccum += real * dqClusterWeight;
iAccum += imag * dqClusterWeight;
}
float norm = length(rAccum);

View file

@ -59,26 +59,37 @@ glm::vec3 DualQuaternion::getTranslation() const {
return glm::vec3(result.x, result.y, result.z);
}
glm::vec3 DualQuaternion::xformVector(const glm::vec3& rhs) const {
return _real * rhs;
}
// AJT: UNTESTED
DualQuaternion DualQuaternion::inverse() const {
glm::quat invReal = glm::inverse(_real);
return DualQuaternion(invReal, - invReal * _imag * invReal);
}
// AJT: UNTESTED
DualQuaternion DualQuaternion::conjugate() const {
return DualQuaternion(glm::conjugate(_real), glm::conjugate(_imag));
}
// AJT: UNTESTED
float DualQuaternion::length() const {
DualQuaternion result = *this * conjugate();
return sqrtf(result._real.w);
float dot = this->dot(*this);
return sqrtf(dot);
}
DualQuaternion DualQuaternion::normalize() const {
float invLen = 1.0f / length();
return *this * invLen;
}
float DualQuaternion::dot(const DualQuaternion& rhs) const {
DualQuaternion result = *this * conjugate();
return result._real.w;
}
DualQuaternion DualQuaternion::operator-() const {
return DualQuaternion(-_real, -_imag);
}

View file

@ -44,6 +44,8 @@ public:
DualQuaternion conjugate() const;
float length() const;
DualQuaternion normalize() const;
float dot(const DualQuaternion& rhs) const;
DualQuaternion operator-() const;
protected:
friend QDebug operator<<(QDebug debug, const DualQuaternion& pose);
@ -51,6 +53,7 @@ protected:
glm::quat _imag;
};
inline QDebug operator<<(QDebug debug, const DualQuaternion& dq) {
debug << "AnimPose, real = (" << dq._real.x << dq._real.y << dq._real.z << dq._real.w << "), imag = (" << dq._imag.x << dq._imag.y << dq._imag.z << dq._imag.w << ")";
return debug;