Full Dual Quaternion support

This commit is contained in:
Anthony J. Thibault 2017-12-21 14:22:22 -08:00
parent 3896b31a72
commit 8bdddf7211
11 changed files with 267 additions and 73 deletions

View file

@ -20,35 +20,19 @@ using namespace render;
CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform)
: ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform) {}
#ifdef SKIN_COMP
void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector<Model::TransformComponents>& clusterTransforms, const std::vector<Model::TransformComponents>& cauterizedClusterTransforms) {
void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector<TransformType>& clusterTransforms, const std::vector<TransformType>& cauterizedClusterTransforms) {
ModelMeshPartPayload::updateClusterBuffer(clusterTransforms);
if (cauterizedClusterTransforms.size() > 1) {
if (!_cauterizedClusterBuffer) {
_cauterizedClusterBuffer = std::make_shared<gpu::Buffer>(cauterizedClusterTransforms.size() * sizeof(Model::TransformComponents),
_cauterizedClusterBuffer = std::make_shared<gpu::Buffer>(cauterizedClusterTransforms.size() * sizeof(TransformType),
(const gpu::Byte*) cauterizedClusterTransforms.data());
} else {
_cauterizedClusterBuffer->setSubData(0, cauterizedClusterTransforms.size() * sizeof(Model::TransformComponents),
_cauterizedClusterBuffer->setSubData(0, cauterizedClusterTransforms.size() * sizeof(TransformType),
(const gpu::Byte*) cauterizedClusterTransforms.data());
}
}
}
#else
void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector<glm::mat4>& clusterTransforms, const std::vector<glm::mat4>& cauterizedClusterTransforms) {
ModelMeshPartPayload::updateClusterBuffer(clusterTransforms);
if (cauterizedClusterTransforms.size() > 1) {
if (!_cauterizedClusterBuffer) {
_cauterizedClusterBuffer = std::make_shared<gpu::Buffer>(cauterizedClusterTransforms.size() * sizeof(glm::mat4),
(const gpu::Byte*) cauterizedClusterTransforms.data());
} else {
_cauterizedClusterBuffer->setSubData(0, cauterizedClusterTransforms.size() * sizeof(glm::mat4),
(const gpu::Byte*) cauterizedClusterTransforms.data());
}
}
}
#endif
void CauterizedMeshPartPayload::updateTransformForCauterizedMesh(const Transform& renderTransform) {
_cauterizedTransform = renderTransform;

View file

@ -14,12 +14,17 @@
class CauterizedMeshPartPayload : public ModelMeshPartPayload {
public:
CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform);
#ifdef SKIN_COMP
void updateClusterBuffer(const std::vector<Model::TransformComponents>& clusterTransforms, const std::vector<Model::TransformComponents>& cauterizedClusterTransforms);
#if defined(SKIN_COMP)
using TransformType = Model::TransformComponents;
#elif defined(SKIN_DQ)
using TransformType = Model::TransformDualQuaternion;
#else
void updateClusterBuffer(const std::vector<glm::mat4>& clusterTransforms, const std::vector<glm::mat4>& cauterizedClusterTransforms);
using TransformType = glm::mat4;
#endif
void updateClusterBuffer(const std::vector<TransformType>& clusterTransforms, const std::vector<TransformType>& cauterizedClusterTransforms);
void updateTransformForCauterizedMesh(const Transform& renderTransform);
void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override;

View file

@ -117,11 +117,16 @@ void CauterizedModel::updateClusterMatrices() {
const FBXCluster& cluster = mesh.clusters.at(j);
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
#ifdef SKIN_COMP
// AJT: TODO: optimize
#if defined(SKIN_COMP)
glm::mat4 m;
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
AnimPose p(m);
state.clusterTransforms[j] = Model::TransformComponents(m);
#elif defined(SKIN_DQ)
glm::mat4 m;
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
AnimPose p(m);
state.clusterTransforms[j] = Model::TransformDualQuaternion(m);
#else
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
#endif
@ -149,11 +154,16 @@ void CauterizedModel::updateClusterMatrices() {
jointMatrix = cauterizeMatrix;
}
#ifdef SKIN_COMP
// AJT: TODO: optimize
#if defined(SKIN_COMP)
glm::mat4 m;
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
AnimPose p(m);
state.clusterTransforms[j] = Model::TransformComponents(m);
#elif defined(SKIN_DQ)
glm::mat4 m;
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
AnimPose p(m);
state.clusterTransforms[j] = Model::TransformDualQuaternion(m);
#else
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
#endif
@ -224,7 +234,7 @@ void CauterizedModel::updateRenderItems() {
Transform renderTransform = modelTransform;
if (clusterTransforms.size() == 1) {
#ifdef SKIN_COMP
#if defined(SKIN_COMP) || defined(SKIN_DQ)
renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0].getMatrix()));
#else
renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0]));
@ -234,7 +244,7 @@ void CauterizedModel::updateRenderItems() {
renderTransform = modelTransform;
if (clusterTransformsCauterized.size() == 1) {
#ifdef SKIN_COMP
#if defined(SKIN_COMP) || defined(SKIN_DQ)
renderTransform = modelTransform.worldTransform(Transform(clusterTransformsCauterized[0].getMatrix()));
#else
renderTransform = modelTransform.worldTransform(Transform(clusterTransformsCauterized[0]));

View file

@ -331,7 +331,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in
updateTransform(transform, offsetTransform);
Transform renderTransform = transform;
if (state.clusterTransforms.size() == 1) {
#ifdef SKIN_COMP
#if defined(SKIN_COMP) || defined(SKIN_DQ)
renderTransform = transform.worldTransform(Transform(state.clusterTransforms[0].getMatrix()));
#else
renderTransform = transform.worldTransform(Transform(state.clusterTransforms[0]));
@ -366,26 +366,11 @@ void ModelMeshPartPayload::notifyLocationChanged() {
}
#ifdef SKIN_COMP
void ModelMeshPartPayload::updateClusterBuffer(const std::vector<Model::TransformComponents>& clusterTransforms) {
void ModelMeshPartPayload::updateClusterBuffer(const std::vector<TransformType>& clusterTransforms) {
// Once computed the cluster matrices, update the buffer(s)
if (clusterTransforms.size() > 1) {
if (!_clusterBuffer) {
_clusterBuffer = std::make_shared<gpu::Buffer>(clusterTransforms.size() * sizeof(Model::TransformComponents),
(const gpu::Byte*) clusterTransforms.data());
}
else {
_clusterBuffer->setSubData(0, clusterTransforms.size() * sizeof(Model::TransformComponents),
(const gpu::Byte*) clusterTransforms.data());
}
}
}
#else
void ModelMeshPartPayload::updateClusterBuffer(const std::vector<glm::mat4>& clusterTransforms) {
// Once computed the cluster matrices, update the buffer(s)
if (clusterTransforms.size() > 1) {
if (!_clusterBuffer) {
_clusterBuffer = std::make_shared<gpu::Buffer>(clusterTransforms.size() * sizeof(glm::mat4),
_clusterBuffer = std::make_shared<gpu::Buffer>(clusterTransforms.size() * sizeof(TransformType),
(const gpu::Byte*) clusterTransforms.data());
}
else {
@ -394,8 +379,6 @@ void ModelMeshPartPayload::updateClusterBuffer(const std::vector<glm::mat4>& clu
}
}
}
#endif
void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform) {
_transform = renderTransform;
@ -561,15 +544,11 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE;
}
#ifdef SKIN_COMP
void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector<Model::TransformComponents>& clusterTransforms) {
#else
void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector<glm::mat4>& clusterTransforms) {
#endif
void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector<TransformType>& clusterTransforms) {
_adjustedLocalBound = _localBound;
if (clusterTransforms.size() > 0) {
#ifdef SKIN_COMP
// AJT: TODO: optimize
#if defined(SKIN_COMP) || defined(SKIN_DQ)
_adjustedLocalBound.transform(clusterTransforms[0].getMatrix());
#else
_adjustedLocalBound.transform(clusterTransforms[0]);
@ -577,8 +556,7 @@ void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector<glm::mat4
for (int i = 1; i < (int)clusterTransforms.size(); ++i) {
AABox clusterBound = _localBound;
#ifdef SKIN_COMP
// AJT: TODO: optimize
#if defined(SKIN_COMP) || defined(SKIN_DQ)
clusterBound.transform(clusterTransforms[i].getMatrix());
#else
clusterBound.transform(clusterTransforms[i]);

View file

@ -87,11 +87,16 @@ public:
typedef Payload::DataPointer Pointer;
void notifyLocationChanged() override;
#ifdef SKIN_COMP
void updateClusterBuffer(const std::vector<Model::TransformComponents>& clusterTransforms);
#if defined(SKIN_COMP)
using TransformType = Model::TransformComponents;
#elif defined(SKIN_DQ)
using TransformType = Model::TransformDualQuaternion;
#else
void updateClusterBuffer(const std::vector<glm::mat4>& clusterTransforms);
using TransformType = glm::mat4;
#endif
void updateClusterBuffer(const std::vector<TransformType>& clusterTransforms);
void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform);
// Render Item interface
@ -108,11 +113,7 @@ public:
void bindMesh(gpu::Batch& batch) override;
void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override;
#ifdef SKIN_COMP
void computeAdjustedLocalBound(const std::vector<Model::TransformComponents>& clusterTransforms);
#else
void computeAdjustedLocalBound(const std::vector<glm::mat4>& clusterMatrices);
#endif
void computeAdjustedLocalBound(const std::vector<TransformType>& clusterTransforms);
gpu::BufferPointer _clusterBuffer;

View file

@ -276,7 +276,7 @@ void Model::updateRenderItems() {
Transform renderTransform = modelTransform;
if (clusterTransforms.size() == 1) {
#ifdef SKIN_COMP
#if defined(SKIN_COMP) || defined(SKIN_DQ)
renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0].getMatrix()));
#else
renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0]));
@ -1183,11 +1183,14 @@ void Model::updateClusterMatrices() {
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
#ifdef SKIN_COMP
// AJT: TODO: optimize
#if defined(SKIN_COMP)
glm::mat4 mat;
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, mat);
state.clusterTransforms[j] = TransformComponents(mat);
#elif defined(SKIN_DQ)
glm::mat4 mat;
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, mat);
state.clusterTransforms[j] = TransformDualQuaternion(mat);
#else
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
#endif

View file

@ -30,6 +30,7 @@
#include <Transform.h>
#include <SpatiallyNestable.h>
#include <TriangleSet.h>
#include <DualQuaternion.h>
#include "GeometryCache.h"
#include "TextureCache.h"
@ -43,7 +44,7 @@
} \
} while(false)
#define SKIN_COMP
#define SKIN_DQ
class AbstractViewStateInterface;
class QScriptEngine;
@ -255,6 +256,7 @@ public:
int getRenderInfoDrawCalls() const { return _renderInfoDrawCalls; }
bool getRenderInfoHasTransparent() const { return _renderInfoHasTransparent; }
#if defined(SKIN_COMP)
class TransformComponents {
public:
TransformComponents() {}
@ -290,15 +292,43 @@ public:
glm::vec4 _trans { 0.0f, 0.0f, 0.0f, 0.0f };
glm::vec4 _padding { 0.0f, 0.0f, 0.0f, 0.0f };
};
#elif defined(SKIN_DQ)
class TransformDualQuaternion {
public:
TransformDualQuaternion() {}
TransformDualQuaternion(const glm::mat4& m) {
AnimPose p(m);
_scale.x = p.scale().x;
_scale.y = p.scale().y;
_scale.z = p.scale().z;
_dq = DualQuaternion(p.rot(), p.trans());
}
TransformDualQuaternion(const glm::vec3& scale, const glm::quat& rot, const glm::vec3& trans) {
_scale.x = scale.x;
_scale.y = scale.y;
_scale.z = scale.z;
_dq = DualQuaternion(rot, trans);
}
glm::vec3 getScale() const { return glm::vec3(_scale); }
glm::quat getRot() const { return _dq.getRotation(); }
glm::vec3 getTrans() const { return _dq.getTranslation(); }
glm::mat4 getMatrix() const { return createMatFromScaleQuatAndPos(getScale(), getRot(), getTrans()); };
protected:
glm::vec4 _scale { 1.0f, 1.0f, 1.0f, 0.0f };
DualQuaternion _dq;
glm::vec4 _padding;
};
#endif
class MeshState {
public:
#ifdef SKIN_COMP
#if defined(SKIN_COMP)
std::vector<TransformComponents> clusterTransforms;
#elif defined(SKIN_DQ)
std::vector<TransformDualQuaternion> clusterTransforms;
#else
std::vector<glm::mat4> clusterTransforms;
#endif
};
const MeshState& getMeshState(int index) { return _meshStates.at(index); }

View file

@ -38,6 +38,181 @@ void dqMul(vec4 lhsReal, vec4 lhsImag, vec4 rhsReal, vec4 rhsImag, out vec4 real
imagOut = quatMul(lhsReal, rhsImag) + quatMul(lhsImag, rhsReal);
}
void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {
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);
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
float clusterWeight = skinClusterWeight[i];
vec3 scale = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]);
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]);
sAccum += scale * clusterWeight;
rAccum += real * clusterWeight;
iAccum += imag * clusterWeight;
}
float norm = length(rAccum);
rAccum /= norm;
iAccum /= norm;
float xe = iAccum.x;
float ye = iAccum.y;
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);
}
void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,
out vec4 skinnedPosition, out vec3 skinnedNormal) {
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);
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
float clusterWeight = skinClusterWeight[i];
vec3 scale = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]);
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]);
sAccum += scale * clusterWeight;
rAccum += real * clusterWeight;
iAccum += imag * clusterWeight;
}
float norm = length(rAccum);
rAccum /= norm;
iAccum /= norm;
float xe = iAccum.x;
float ye = iAccum.y;
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);
skinnedNormal = vec3(m * vec4(inNormal, 0));
}
void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,
out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {
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);
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
float clusterWeight = skinClusterWeight[i];
vec3 scale = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]);
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]);
sAccum += scale * clusterWeight;
rAccum += real * clusterWeight;
iAccum += imag * clusterWeight;
}
float norm = length(rAccum);
rAccum /= norm;
iAccum /= norm;
float xe = iAccum.x;
float ye = iAccum.y;
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);
skinnedNormal = vec3(m * vec4(inNormal, 0));
skinnedTangent = vec3(m * vec4(inTangent, 0));
}
// SKIN_COMP
/*
void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {
vec3 sAccum = vec3(0.0, 0.0, 0.0);
vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);
@ -125,6 +300,7 @@ void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, v
skinnedNormal = rotateByQuat(rAccum, inNormal);
skinnedTangent = rotateByQuat(rAccum, inTangent);
}
*/
/*
// ORIGINAL

View file

@ -58,11 +58,14 @@ void SoftAttachmentModel::updateClusterMatrices() {
} else {
jointMatrix = _rig.getJointTransform(cluster.jointIndex);
}
#ifdef SKIN_COMP
// AJT: TODO: Optimize
#if defined(SKIN_COMP)
glm::mat4 m;
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
state.clusterTransforms[j] = Model::TransformComponents(m);
#elif defined(SKIN_DQ)
glm::mat4 m;
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
state.clusterTransforms[j] = Model::TransformDualQuaternion(m);
#else
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]);
#endif

View file

@ -12,6 +12,9 @@
#include "GLMHelpers.h"
// delegating constructor
DualQuaternion::DualQuaternion() : _real(1.0f, 0.0f, 0.0f, 0.0), _imag(0.0f, 0.0f, 0.0f, 0.0f) {
}
DualQuaternion::DualQuaternion(const glm::mat4& m) : DualQuaternion(glmExtractRotation(m), extractTranslation(m)) {
}

View file

@ -19,6 +19,7 @@
class DualQuaternion {
public:
DualQuaternion();
explicit DualQuaternion(const glm::mat4& m);
DualQuaternion(const glm::quat& real, const glm::quat& imag);
DualQuaternion(const glm::quat& rotation, const glm::vec3& translation);