Optimizations and cleanup

This commit is contained in:
Anthony J. Thibault 2017-12-22 15:24:54 -08:00
parent e86fd4f992
commit bcd813ac62
7 changed files with 113 additions and 193 deletions

View file

@ -112,9 +112,9 @@ void CauterizedModel::updateClusterMatrices() {
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
#if defined(SKIN_DQ) #if defined(SKIN_DQ)
// AJT: TODO: optimize
glm::mat4 m; glm::mat4 m;
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m); glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
AnimPose p(m);
state.clusterTransforms[j] = Model::TransformDualQuaternion(m); state.clusterTransforms[j] = Model::TransformDualQuaternion(m);
#else #else
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]); glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
@ -145,9 +145,9 @@ void CauterizedModel::updateClusterMatrices() {
} }
#if defined(SKIN_DQ) #if defined(SKIN_DQ)
// AJT: TODO: optimize
glm::mat4 m; glm::mat4 m;
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m); glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
AnimPose p(m);
state.clusterTransforms[j] = Model::TransformDualQuaternion(m); state.clusterTransforms[j] = Model::TransformDualQuaternion(m);
#else #else
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]); glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
@ -220,7 +220,10 @@ void CauterizedModel::updateRenderItems() {
Transform renderTransform = modelTransform; Transform renderTransform = modelTransform;
if (clusterTransforms.size() == 1) { if (clusterTransforms.size() == 1) {
#if defined(SKIN_DQ) #if defined(SKIN_DQ)
renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0].getMatrix())); Transform transform(clusterTransforms[0].getRotation(),
clusterTransforms[0].getScale(),
clusterTransforms[0].getTranslation());
renderTransform = modelTransform.worldTransform(transform);
#else #else
renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0])); renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0]));
#endif #endif
@ -230,7 +233,10 @@ void CauterizedModel::updateRenderItems() {
renderTransform = modelTransform; renderTransform = modelTransform;
if (clusterTransformsCauterized.size() == 1) { if (clusterTransformsCauterized.size() == 1) {
#if defined(SKIN_DQ) #if defined(SKIN_DQ)
renderTransform = modelTransform.worldTransform(Transform(clusterTransformsCauterized[0].getMatrix())); Transform transform(clusterTransforms[0].getRotation(),
clusterTransforms[0].getScale(),
clusterTransforms[0].getTranslation());
renderTransform = modelTransform.worldTransform(Transform(transform));
#else #else
renderTransform = modelTransform.worldTransform(Transform(clusterTransformsCauterized[0])); renderTransform = modelTransform.worldTransform(Transform(clusterTransformsCauterized[0]));
#endif #endif

View file

@ -332,7 +332,10 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in
Transform renderTransform = transform; Transform renderTransform = transform;
if (state.clusterTransforms.size() == 1) { if (state.clusterTransforms.size() == 1) {
#if defined(SKIN_DQ) #if defined(SKIN_DQ)
renderTransform = transform.worldTransform(Transform(state.clusterTransforms[0].getMatrix())); Transform transform(state.clusterTransforms[0].getRotation(),
state.clusterTransforms[0].getScale(),
state.clusterTransforms[0].getTranslation());
renderTransform = transform.worldTransform(Transform(transform));
#else #else
renderTransform = transform.worldTransform(Transform(state.clusterTransforms[0])); renderTransform = transform.worldTransform(Transform(state.clusterTransforms[0]));
#endif #endif
@ -549,7 +552,10 @@ void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector<Transform
_adjustedLocalBound = _localBound; _adjustedLocalBound = _localBound;
if (clusterTransforms.size() > 0) { if (clusterTransforms.size() > 0) {
#if defined(SKIN_DQ) #if defined(SKIN_DQ)
_adjustedLocalBound.transform(clusterTransforms[0].getMatrix()); Transform rootTransform(clusterTransforms[0].getRotation(),
clusterTransforms[0].getScale(),
clusterTransforms[0].getTranslation());
_adjustedLocalBound.transform(rootTransform);
#else #else
_adjustedLocalBound.transform(clusterTransforms[0]); _adjustedLocalBound.transform(clusterTransforms[0]);
#endif #endif
@ -557,7 +563,10 @@ void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector<Transform
for (int i = 1; i < (int)clusterTransforms.size(); ++i) { for (int i = 1; i < (int)clusterTransforms.size(); ++i) {
AABox clusterBound = _localBound; AABox clusterBound = _localBound;
#if defined(SKIN_DQ) #if defined(SKIN_DQ)
clusterBound.transform(clusterTransforms[i].getMatrix()); Transform transform(clusterTransforms[i].getRotation(),
clusterTransforms[i].getScale(),
clusterTransforms[i].getTranslation());
clusterBound.transform(transform);
#else #else
clusterBound.transform(clusterTransforms[i]); clusterBound.transform(clusterTransforms[i]);
#endif #endif

View file

@ -277,7 +277,10 @@ void Model::updateRenderItems() {
Transform renderTransform = modelTransform; Transform renderTransform = modelTransform;
if (clusterTransforms.size() == 1) { if (clusterTransforms.size() == 1) {
#if defined(SKIN_DQ) #if defined(SKIN_DQ)
renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0].getMatrix())); Transform transform(clusterTransforms[0].getRotation(),
clusterTransforms[0].getScale(),
clusterTransforms[0].getTranslation());
renderTransform = modelTransform.worldTransform(Transform(transform));
#else #else
renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0])); renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0]));
#endif #endif
@ -1184,6 +1187,7 @@ 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)
// AJT: TODO: optimize
glm::mat4 mat; glm::mat4 mat;
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, mat); glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, mat);
state.clusterTransforms[j] = TransformDualQuaternion(mat); state.clusterTransforms[j] = TransformDualQuaternion(mat);

View file

@ -36,14 +36,8 @@
#include "TextureCache.h" #include "TextureCache.h"
#include "Rig.h" #include "Rig.h"
#define SKIN_ASSERT(cond) \ // Use dual quaternion skinning!
do { \ // Must match define in Skinning.slh
if (!(cond)) { \
int* p = 0; \
*p = 0xbadf00d; \
} \
} while(false)
#define SKIN_DQ #define SKIN_DQ
class AbstractViewStateInterface; class AbstractViewStateInterface;
@ -275,9 +269,9 @@ public:
_dq = DualQuaternion(rot, trans); _dq = DualQuaternion(rot, trans);
} }
glm::vec3 getScale() const { return glm::vec3(_scale); } glm::vec3 getScale() const { return glm::vec3(_scale); }
glm::quat getRot() const { return _dq.getRotation(); } glm::quat getRotation() const { return _dq.getRotation(); }
glm::vec3 getTrans() const { return _dq.getTranslation(); } glm::vec3 getTranslation() const { return _dq.getTranslation(); }
glm::mat4 getMatrix() const { return createMatFromScaleQuatAndPos(getScale(), getRot(), getTrans()); }; glm::mat4 getMatrix() const { return createMatFromScaleQuatAndPos(getScale(), getRotation(), getTranslation()); };
protected: protected:
glm::vec4 _scale { 1.0f, 1.0f, 1.0f, 0.0f }; glm::vec4 _scale { 1.0f, 1.0f, 1.0f, 0.0f };
DualQuaternion _dq; DualQuaternion _dq;

View file

@ -11,6 +11,10 @@
<@if not SKINNING_SLH@> <@if not SKINNING_SLH@>
<@def SKINNING_SLH@> <@def SKINNING_SLH@>
// Use dual quaternion skinning
// Must match #define SKIN_DQ in Model.h
<@def SKIN_DQ@>
const int MAX_CLUSTERS = 128; const int MAX_CLUSTERS = 128;
const int INDICES_PER_VERTEX = 4; const int INDICES_PER_VERTEX = 4;
@ -18,33 +22,46 @@ layout(std140) uniform skinClusterBuffer {
mat4 clusterMatrices[MAX_CLUSTERS]; mat4 clusterMatrices[MAX_CLUSTERS];
}; };
vec4 quatConj(vec4 v) { <@if SKIN_DQ@>
return vec4(-v.x, -v.y, -v.z, v.w);
} mat4 dualQuatToMat4(vec4 real, vec4 imag) {
float twoRealXSq = 2.0 * real.x * real.x;
vec4 quatMul(vec4 q1, vec4 q2) { float twoRealYSq = 2.0 * real.y * real.y;
return vec4( q1.x * q2.w + q1.y * q2.z - q1.z * q2.y + q1.w * q2.x, float twoRealZSq = 2.0 * real.z * real.z;
-q1.x * q2.z + q1.y * q2.w + q1.z * q2.x + q1.w * q2.y, float twoRealXY = 2.0 * real.x * real.y;
q1.x * q2.y - q1.y * q2.x + q1.z * q2.w + q1.w * q2.z, float twoRealXZ = 2.0 * real.x * real.z;
-q1.x * q2.x - q1.y * q2.y - q1.z * q2.z + q1.w * q2.w); float twoRealXW = 2.0 * real.x * real.w;
} float twoRealZW = 2.0 * real.z * real.w;
float twoRealYZ = 2.0 * real.y * real.z;
vec3 rotateByQuat(vec4 q, vec3 p) { float twoRealYW = 2.0 * real.y * real.w;
return vec3(quatMul(quatMul(q, vec4(p.x, p.y, p.z, 0.0)), quatConj(q))); vec4 col0 = vec4(1.0 - twoRealYSq - twoRealZSq,
} twoRealXY + twoRealZW,
twoRealXZ - twoRealYW,
void dqMul(vec4 lhsReal, vec4 lhsImag, vec4 rhsReal, vec4 rhsImag, out vec4 realOut, out vec4 imagOut) { 0.0);
realOut = quatMul(lhsReal, rhsReal); vec4 col1 = vec4(twoRealXY - twoRealZW,
imagOut = quatMul(lhsReal, rhsImag) + quatMul(lhsImag, rhsReal); 1 - twoRealXSq - twoRealZSq,
twoRealYZ + twoRealXW,
0.0);
vec4 col2 = vec4(twoRealXZ + twoRealYW,
twoRealYZ - twoRealXW,
1 - twoRealXSq - twoRealYSq,
0.0);
vec4 col3 = vec4(2.0 * (-imag.w * real.x + imag.x * real.w - imag.y * real.z + imag.z * real.y),
2.0 * (-imag.w * real.y + imag.x * real.z + imag.y * real.w - imag.z * real.x),
2.0 * (-imag.w * real.z - imag.x * real.y + imag.y * real.x + imag.z * real.w),
1.0);
return mat4(col0, col1, col2, col3);
} }
// dual quaternion linear blending
void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) { void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {
// linearly blend scale and dual quaternion components
vec3 sAccum = vec3(0.0, 0.0, 0.0); vec3 sAccum = vec3(0.0, 0.0, 0.0);
vec4 rAccum = vec4(0.0, 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 iAccum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1]; vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];
for (int i = 0; i < INDICES_PER_VERTEX; i++) { for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])]; mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
float clusterWeight = skinClusterWeight[i]; float clusterWeight = skinClusterWeight[i];
@ -64,46 +81,20 @@ void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPositio
iAccum += imag * dqClusterWeight; iAccum += imag * dqClusterWeight;
} }
// normalize dual quaternion
float norm = length(rAccum); float norm = length(rAccum);
rAccum /= norm; rAccum /= norm;
iAccum /= norm; iAccum /= norm;
float xe = iAccum.x; // conversion from dual quaternion to 4x4 matrix.
float ye = iAccum.y; mat4 m = dualQuatToMat4(rAccum, iAccum);
float ze = iAccum.z;
float we = iAccum.w;
float x0 = rAccum.x;
float y0 = rAccum.y;
float z0 = rAccum.z;
float w0 = rAccum.w;
float t0 = 2.0 * (-we * x0 + xe * w0 - ye * z0 + ze * y0);
float t1 = 2.0 * (-we * y0 + xe * z0 + ye * w0 - ze * x0);
float t2 = 2.0 * (-we * z0 - xe * y0 + ye * x0 + ze * w0);
vec4 col0 = vec4(1.0 - 2.0 * y0 * y0 - 2.0 * z0 * z0,
2.0 * x0 * y0 + 2.0 * w0 * z0,
2.0 * x0 * z0 - 2.0 * w0 * y0,
0.0);
vec4 col1 = vec4(2.0 * x0 * y0 - 2.0 * w0 * z0,
1 - 2.0 * x0 * x0 - 2.0 * z0 * z0,
2.0 * y0 * z0 + 2.0 * w0 * x0,
0.0);
vec4 col2 = vec4(2.0 * x0 * z0 + 2.0 * w0 * y0,
2.0 * y0 * z0 - 2.0 * w0 * x0,
1 - 2.0 * x0 * x0 - 2.0 * y0 * y0,
0.0);
vec4 col3 = vec4(t0, t1, t2, 1.0);
mat4 m = mat4(col0, col1, col2, col3);
skinnedPosition = m * (vec4(sAccum, 1) * inPosition); skinnedPosition = m * (vec4(sAccum, 1) * inPosition);
} }
void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,
out vec4 skinnedPosition, out vec3 skinnedNormal) { out vec4 skinnedPosition, out vec3 skinnedNormal) {
// linearly blend scale and dual quaternion components
vec3 sAccum = vec3(0.0, 0.0, 0.0); vec3 sAccum = vec3(0.0, 0.0, 0.0);
vec4 rAccum = vec4(0.0, 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 iAccum = vec4(0.0, 0.0, 0.0, 0.0);
@ -128,40 +119,13 @@ void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inP
iAccum += imag * dqClusterWeight; iAccum += imag * dqClusterWeight;
} }
// normalize dual quaternion
float norm = length(rAccum); float norm = length(rAccum);
rAccum /= norm; rAccum /= norm;
iAccum /= norm; iAccum /= norm;
float xe = iAccum.x; // conversion from dual quaternion to 4x4 matrix.
float ye = iAccum.y; mat4 m = dualQuatToMat4(rAccum, iAccum);
float ze = iAccum.z;
float we = iAccum.w;
float x0 = rAccum.x;
float y0 = rAccum.y;
float z0 = rAccum.z;
float w0 = rAccum.w;
float t0 = 2.0 * (-we * x0 + xe * w0 - ye * z0 + ze * y0);
float t1 = 2.0 * (-we * y0 + xe * z0 + ye * w0 - ze * x0);
float t2 = 2.0 * (-we * z0 - xe * y0 + ye * x0 + ze * w0);
vec4 col0 = vec4(1.0 - 2.0 * y0 * y0 - 2.0 * z0 * z0,
2.0 * x0 * y0 + 2.0 * w0 * z0,
2.0 * x0 * z0 - 2.0 * w0 * y0,
0.0);
vec4 col1 = vec4(2.0 * x0 * y0 - 2.0 * w0 * z0,
1 - 2.0 * x0 * x0 - 2.0 * z0 * z0,
2.0 * y0 * z0 + 2.0 * w0 * x0,
0.0);
vec4 col2 = vec4(2.0 * x0 * z0 + 2.0 * w0 * y0,
2.0 * y0 * z0 - 2.0 * w0 * x0,
1 - 2.0 * x0 * x0 - 2.0 * y0 * y0,
0.0);
vec4 col3 = vec4(t0, t1, t2, 1.0);
mat4 m = mat4(col0, col1, col2, col3);
skinnedPosition = m * (vec4(sAccum, 1) * inPosition); skinnedPosition = m * (vec4(sAccum, 1) * inPosition);
skinnedNormal = vec3(m * vec4(inNormal, 0)); skinnedNormal = vec3(m * vec4(inNormal, 0));
} }
@ -169,6 +133,7 @@ void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inP
void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent, void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,
out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) { out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {
// linearly blend scale and dual quaternion components
vec3 sAccum = vec3(0.0, 0.0, 0.0); vec3 sAccum = vec3(0.0, 0.0, 0.0);
vec4 rAccum = vec4(0.0, 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 iAccum = vec4(0.0, 0.0, 0.0, 0.0);
@ -193,134 +158,67 @@ void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, v
iAccum += imag * dqClusterWeight; iAccum += imag * dqClusterWeight;
} }
// normalize dual quaternion
float norm = length(rAccum); float norm = length(rAccum);
rAccum /= norm; rAccum /= norm;
iAccum /= norm; iAccum /= norm;
float xe = iAccum.x; // conversion from dual quaternion to 4x4 matrix.
float ye = iAccum.y; mat4 m = dualQuatToMat4(rAccum, iAccum);
float ze = iAccum.z;
float we = iAccum.w;
float x0 = rAccum.x;
float y0 = rAccum.y;
float z0 = rAccum.z;
float w0 = rAccum.w;
float t0 = 2.0 * (-we * x0 + xe * w0 - ye * z0 + ze * y0);
float t1 = 2.0 * (-we * y0 + xe * z0 + ye * w0 - ze * x0);
float t2 = 2.0 * (-we * z0 - xe * y0 + ye * x0 + ze * w0);
vec4 col0 = vec4(1.0 - 2.0 * y0 * y0 - 2.0 * z0 * z0,
2.0 * x0 * y0 + 2.0 * w0 * z0,
2.0 * x0 * z0 - 2.0 * w0 * y0,
0.0);
vec4 col1 = vec4(2.0 * x0 * y0 - 2.0 * w0 * z0,
1 - 2.0 * x0 * x0 - 2.0 * z0 * z0,
2.0 * y0 * z0 + 2.0 * w0 * x0,
0.0);
vec4 col2 = vec4(2.0 * x0 * z0 + 2.0 * w0 * y0,
2.0 * y0 * z0 - 2.0 * w0 * x0,
1 - 2.0 * x0 * x0 - 2.0 * y0 * y0,
0.0);
vec4 col3 = vec4(t0, t1, t2, 1.0);
mat4 m = mat4(col0, col1, col2, col3);
skinnedPosition = m * (vec4(sAccum, 1) * inPosition); skinnedPosition = m * (vec4(sAccum, 1) * inPosition);
skinnedNormal = vec3(m * vec4(inNormal, 0)); skinnedNormal = vec3(m * vec4(inNormal, 0));
skinnedTangent = vec3(m * vec4(inTangent, 0)); skinnedTangent = vec3(m * vec4(inTangent, 0));
} }
// SKIN_COMP <@else@> // SKIN_DQ
/*
void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) { void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {
vec3 sAccum = vec3(0.0, 0.0, 0.0); vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);
vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);
vec3 tAccum = vec3(0.0, 0.0, 0.0);
for (int i = 0; i < INDICES_PER_VERTEX; i++) { for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])]; mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
float clusterWeight = skinClusterWeight[i]; float clusterWeight = skinClusterWeight[i];
newPosition += clusterMatrix * inPosition * clusterWeight;
vec3 s = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]);
vec4 r = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]);
vec3 t = vec3(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2]);
if (dot(r, rAccum) < 0) {
r = -r;
} }
sAccum += s * clusterWeight; skinnedPosition = newPosition;
rAccum += r * clusterWeight;
tAccum += t * clusterWeight;
}
rAccum = normalize(rAccum);
skinnedPosition = vec4(rotateByQuat(rAccum, (vec3(inPosition) * sAccum)) + tAccum, 1);
} }
void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,
out vec4 skinnedPosition, out vec3 skinnedNormal) { out vec4 skinnedPosition, out vec3 skinnedNormal) {
vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);
vec3 sAccum = vec3(0.0, 0.0, 0.0); vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);
vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);
vec3 tAccum = vec3(0.0, 0.0, 0.0);
for (int i = 0; i < INDICES_PER_VERTEX; i++) { for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])]; mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
float clusterWeight = skinClusterWeight[i]; float clusterWeight = skinClusterWeight[i];
newPosition += clusterMatrix * inPosition * clusterWeight;
vec3 s = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]); newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;
vec4 r = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]);
vec3 t = vec3(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2]);
if (dot(r, rAccum) < 0) {
r = -r;
} }
sAccum += s * clusterWeight; skinnedPosition = newPosition;
rAccum += r * clusterWeight; skinnedNormal = newNormal.xyz;
tAccum += t * clusterWeight;
}
rAccum = normalize(rAccum);
skinnedPosition = vec4(rotateByQuat(rAccum, (vec3(inPosition) * sAccum)) + tAccum, 1);
skinnedNormal = rotateByQuat(rAccum, inNormal);
} }
void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent, void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,
out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) { out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {
vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);
vec3 sAccum = vec3(0.0, 0.0, 0.0); vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);
vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0); vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);
vec3 tAccum = vec3(0.0, 0.0, 0.0);
for (int i = 0; i < INDICES_PER_VERTEX; i++) { for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])]; mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
float clusterWeight = skinClusterWeight[i]; float clusterWeight = skinClusterWeight[i];
newPosition += clusterMatrix * inPosition * clusterWeight;
vec3 s = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]); newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;
vec4 r = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]); newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;
vec3 t = vec3(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2]);
if (dot(r, rAccum) < 0) {
r = -r;
} }
sAccum += s * clusterWeight; skinnedPosition = newPosition;
rAccum += r * clusterWeight; skinnedNormal = newNormal.xyz;
tAccum += t * clusterWeight; skinnedTangent = newTangent.xyz;
} }
rAccum = normalize(rAccum); <@endif@> // if SKIN_DQ
skinnedPosition = vec4(rotateByQuat(rAccum, (vec3(inPosition) * sAccum)) + tAccum, 1); <@endif@> // if not SKINNING_SLH
skinnedNormal = rotateByQuat(rAccum, inNormal);
skinnedTangent = rotateByQuat(rAccum, inTangent);
}
*/
<@endif@>

View file

@ -52,17 +52,26 @@ void SoftAttachmentModel::updateClusterMatrices() {
// TODO: cache these look-ups as an optimization // TODO: cache these look-ups as an optimization
int jointIndexOverride = getJointIndexOverride(cluster.jointIndex); int jointIndexOverride = getJointIndexOverride(cluster.jointIndex);
#if defined(SKIN_DQ)
glm::mat4 jointMatrix; glm::mat4 jointMatrix;
if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) { if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) {
jointMatrix = _rigOverride.getJointTransform(jointIndexOverride); jointMatrix = _rigOverride.getJointTransform(jointIndexOverride);
} else { } else {
jointMatrix = _rig.getJointTransform(cluster.jointIndex); jointMatrix = _rig.getJointTransform(cluster.jointIndex);
} }
#if defined(SKIN_DQ)
// AJT: TODO: OPTIMIZE
glm::mat4 m; glm::mat4 m;
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m); glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
state.clusterTransforms[j] = Model::TransformDualQuaternion(m); state.clusterTransforms[j] = Model::TransformDualQuaternion(m);
#else #else
glm::mat4 jointMatrix;
if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) {
jointMatrix = _rigOverride.getJointTransform(jointIndexOverride);
} else {
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
} }

View file

@ -58,7 +58,7 @@ public:
_rotation(rotation), _rotation(rotation),
_scale(scale), _scale(scale),
_translation(translation), _translation(translation),
_flags(FLAG_CACHE_INVALID_BITSET) // invalid cache _flags(0xf) // FLAG_TRANSLATION | FLAG_ROTATION | FLAG_SCALING | FLAG_NON_UNIFORM
{ {
if (!isValidScale(_scale)) { if (!isValidScale(_scale)) {
_scale = Vec3(1.0f); _scale = Vec3(1.0f);