mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
Switch between dualQuats and matrix skinning based on model entity scale factor.
This commit is contained in:
parent
86351f19a9
commit
0469eafbe4
9 changed files with 37 additions and 11 deletions
|
@ -133,6 +133,9 @@ void RenderableModelEntityItem::doInitialModelSimulation() {
|
|||
model->setRotation(getWorldOrientation());
|
||||
model->setTranslation(getWorldPosition());
|
||||
|
||||
glm::vec3 scale = model->getScale();
|
||||
model->setUseDualQuaternionSkinning(!isNonUniformScale(scale));
|
||||
|
||||
if (_needsInitialSimulation) {
|
||||
model->simulate(0.0f);
|
||||
_needsInitialSimulation = false;
|
||||
|
@ -243,6 +246,8 @@ void RenderableModelEntityItem::updateModelBounds() {
|
|||
}
|
||||
|
||||
if (updateRenderItems) {
|
||||
glm::vec3 scale = model->getScale();
|
||||
model->setUseDualQuaternionSkinning(!isNonUniformScale(scale));
|
||||
model->updateRenderItems();
|
||||
}
|
||||
}
|
||||
|
@ -1500,4 +1505,4 @@ void ModelEntityRenderer::processMaterials() {
|
|||
material.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -407,7 +407,7 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe
|
|||
if (isWireframe) {
|
||||
builder.withWireframe();
|
||||
}
|
||||
if (_useDualQuaternionSkinning) {
|
||||
if (_useDualQuaternionSkinning && isSkinned) {
|
||||
builder.withDualQuatSkinned();
|
||||
}
|
||||
|
||||
|
@ -497,3 +497,10 @@ void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector<Model::Tr
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelMeshPartPayload::setUseDualQuaternionSkinning(bool value) {
|
||||
if (value != _useDualQuaternionSkinning) {
|
||||
_clusterBuffer.reset();
|
||||
}
|
||||
_useDualQuaternionSkinning = value;
|
||||
}
|
||||
|
|
|
@ -120,6 +120,8 @@ public:
|
|||
// dual quaternion skinning
|
||||
void computeAdjustedLocalBound(const std::vector<Model::TransformDualQuaternion>& clusterDualQuaternions);
|
||||
|
||||
void setUseDualQuaternionSkinning(bool value);
|
||||
|
||||
gpu::BufferPointer _clusterBuffer;
|
||||
|
||||
int _meshIndex;
|
||||
|
|
|
@ -288,6 +288,7 @@ void Model::updateRenderItems() {
|
|||
invalidatePayloadShapeKey, isWireframe, isVisible,
|
||||
viewTagBits, isLayeredInFront,
|
||||
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
||||
data.setUseDualQuaternionSkinning(useDualQuaternionSkinning);
|
||||
if (useDualQuaternionSkinning) {
|
||||
data.updateClusterBuffer(meshState.clusterDualQuaternions);
|
||||
} else {
|
||||
|
@ -388,11 +389,8 @@ bool Model::updateGeometry() {
|
|||
const FBXGeometry& fbxGeometry = getFBXGeometry();
|
||||
foreach (const FBXMesh& mesh, fbxGeometry.meshes) {
|
||||
MeshState state;
|
||||
if (_useDualQuaternionSkinning) {
|
||||
state.clusterDualQuaternions.resize(mesh.clusters.size());
|
||||
} else {
|
||||
state.clusterMatrices.resize(mesh.clusters.size());
|
||||
}
|
||||
state.clusterDualQuaternions.resize(mesh.clusters.size());
|
||||
state.clusterMatrices.resize(mesh.clusters.size());
|
||||
_meshStates.push_back(state);
|
||||
|
||||
// Note: we add empty buffers for meshes that lack blendshapes so we can access the buffers by index
|
||||
|
@ -1248,6 +1246,10 @@ void Model::snapToRegistrationPoint() {
|
|||
_snappedToRegistrationPoint = true;
|
||||
}
|
||||
|
||||
void Model::setUseDualQuaternionSkinning(bool value) {
|
||||
_useDualQuaternionSkinning = value;
|
||||
}
|
||||
|
||||
void Model::simulate(float deltaTime, bool fullUpdate) {
|
||||
DETAILED_PROFILE_RANGE(simulation_detail, __FUNCTION__);
|
||||
fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit)
|
||||
|
@ -1583,11 +1585,13 @@ void Model::addMaterial(graphics::MaterialLayer material, const std::string& par
|
|||
bool wireframe = isWireframe();
|
||||
auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex;
|
||||
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
||||
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
|
||||
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits,
|
||||
invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) {
|
||||
invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) {
|
||||
data.addMaterial(material);
|
||||
// if the material changed, we might need to update our item key or shape key
|
||||
data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits);
|
||||
data.setUseDualQuaternionSkinning(useDualQuaternionSkinning);
|
||||
data.setShapeKey(invalidatePayloadShapeKey, wireframe);
|
||||
});
|
||||
}
|
||||
|
@ -1608,11 +1612,13 @@ void Model::removeMaterial(graphics::MaterialPointer material, const std::string
|
|||
bool wireframe = isWireframe();
|
||||
auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex;
|
||||
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
||||
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
|
||||
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits,
|
||||
invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) {
|
||||
invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) {
|
||||
data.removeMaterial(material);
|
||||
// if the material changed, we might need to update our item key or shape key
|
||||
data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits);
|
||||
data.setUseDualQuaternionSkinning(useDualQuaternionSkinning);
|
||||
data.setShapeKey(invalidatePayloadShapeKey, wireframe);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -314,6 +314,7 @@ public:
|
|||
|
||||
void scaleToFit();
|
||||
bool getUseDualQuaternionSkinning() const { return _useDualQuaternionSkinning; }
|
||||
void setUseDualQuaternionSkinning(bool value);
|
||||
|
||||
void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName);
|
||||
void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName);
|
||||
|
|
|
@ -447,7 +447,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
|
|||
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular().withFade(),
|
||||
skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter);
|
||||
|
||||
// dual quatenion skinned
|
||||
// dual quaternion skinned
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withSkinned().withDualQuatSkinned(),
|
||||
skinModelDualQuatVertex, modelPixel, nullptr, nullptr);
|
||||
|
|
|
@ -55,7 +55,7 @@ protected:
|
|||
|
||||
|
||||
inline QDebug operator<<(QDebug debug, const DualQuaternion& dq) {
|
||||
debug << "AnimPose, real = (" << dq._real.x << dq._real.y << dq._real.z << dq._real.w << "), dual = (" << dq._dual.x << dq._dual.y << dq._dual.z << dq._dual.w << ")";
|
||||
debug << "DualQuaternion, real = (" << dq._real.x << dq._real.y << dq._real.z << dq._real.w << "), dual = (" << dq._dual.x << dq._dual.y << dq._dual.z << dq._dual.w << ")";
|
||||
return debug;
|
||||
}
|
||||
|
||||
|
|
|
@ -601,3 +601,6 @@ glm::vec3 randVector() {
|
|||
return glm::vec3(randFloat() - 0.5f, randFloat() - 0.5f, randFloat() - 0.5f) * 2.0f;
|
||||
}
|
||||
|
||||
bool isNonUniformScale(const glm::vec3& scale) {
|
||||
return fabsf(scale.x - scale.y) > EPSILON || fabsf(scale.y - scale.z) > EPSILON;
|
||||
}
|
||||
|
|
|
@ -260,6 +260,8 @@ glm::mat4 orthoInverse(const glm::mat4& m);
|
|||
// Return a random vector of average length 1
|
||||
glm::vec3 randVector();
|
||||
|
||||
bool isNonUniformScale(const glm::vec3& scale);
|
||||
|
||||
//
|
||||
// Safe replacement of glm_mat4_mul() for unaligned arguments instead of __m128
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue