mirror of
https://github.com/overte-org/overte.git
synced 2025-08-16 08:11:59 +02:00
Full Dual Quaternion support
This commit is contained in:
parent
3896b31a72
commit
8bdddf7211
11 changed files with 267 additions and 73 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]));
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue