mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 23:53:26 +02:00
WIP: Dual Quaternion compensation for spinning the right way.
This commit is contained in:
parent
8bdddf7211
commit
5bb0b06061
5 changed files with 104 additions and 11 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue