mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 06:44:06 +02:00
Added SoftAttachmentModel class.
Is a subclass of Model, it overrides the updateClusterMatrices so it will pull the actual joint matrices from a different rig override. For the avatar soft attachment system, this override will be the Avatar::_skeletonModel rig. This will give us the ability for an avatar to "wear" non-rigid attachments, such as clothing.
This commit is contained in:
parent
1bb6ddb99f
commit
6b5b272cd7
6 changed files with 131 additions and 3 deletions
83
interface/src/avatar/SoftAttachmentModel.cpp
Normal file
83
interface/src/avatar/SoftAttachmentModel.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
//
|
||||
// SoftAttachmentModel.cpp
|
||||
// interface/src/avatar
|
||||
//
|
||||
// Created by Anthony J. Thibault on 12/17/15.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "SoftAttachmentModel.h"
|
||||
|
||||
SoftAttachmentModel::SoftAttachmentModel(RigPointer rig, QObject* parent, RigPointer rigOverride) :
|
||||
Model(rig, parent),
|
||||
_rigOverride(rigOverride) {
|
||||
assert(_rig);
|
||||
assert(_rigOverride);
|
||||
}
|
||||
|
||||
SoftAttachmentModel::~SoftAttachmentModel() {
|
||||
}
|
||||
|
||||
// virtual
|
||||
void SoftAttachmentModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||
_needsUpdateClusterMatrices = true;
|
||||
}
|
||||
|
||||
int SoftAttachmentModel::getJointIndexOverride(int i) const {
|
||||
QString name = _rig->nameOfJoint(i);
|
||||
if (name.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
return _rigOverride->indexOfJoint(name);
|
||||
}
|
||||
|
||||
// virtual
|
||||
// use the _rigOverride matrices instead of the Model::_rig
|
||||
void SoftAttachmentModel::updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation) {
|
||||
if (!_needsUpdateClusterMatrices) {
|
||||
return;
|
||||
}
|
||||
_needsUpdateClusterMatrices = false;
|
||||
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
|
||||
glm::mat4 modelToWorld = glm::mat4_cast(modelOrientation);
|
||||
for (int i = 0; i < _meshStates.size(); i++) {
|
||||
MeshState& state = _meshStates[i];
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
|
||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||
|
||||
// TODO: cache these look ups as an optimization
|
||||
int jointIndexOverride = getJointIndexOverride(cluster.jointIndex);
|
||||
glm::mat4 jointMatrix(glm::mat4::_null);
|
||||
if (jointIndexOverride >= 0 && jointIndexOverride < getJointStateCount()) {
|
||||
jointMatrix = _rigOverride->getJointTransform(jointIndexOverride);
|
||||
} else {
|
||||
jointMatrix = _rig->getJointTransform(cluster.jointIndex);
|
||||
}
|
||||
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
|
||||
}
|
||||
|
||||
// Once computed the cluster matrices, update the buffer(s)
|
||||
if (mesh.clusters.size() > 1) {
|
||||
if (!state.clusterBuffer) {
|
||||
state.clusterBuffer = std::make_shared<gpu::Buffer>(state.clusterMatrices.size() * sizeof(glm::mat4),
|
||||
(const gpu::Byte*) state.clusterMatrices.constData());
|
||||
} else {
|
||||
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4),
|
||||
(const gpu::Byte*) state.clusterMatrices.constData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// post the blender if we're not currently waiting for one to finish
|
||||
if (geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
|
||||
_blendedBlendshapeCoefficients = _blendshapeCoefficients;
|
||||
DependencyManager::get<ModelBlender>()->noteRequiresBlend(this);
|
||||
}
|
||||
}
|
34
interface/src/avatar/SoftAttachmentModel.h
Normal file
34
interface/src/avatar/SoftAttachmentModel.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// SoftAttachmentModel.h
|
||||
// interface/src/avatar
|
||||
//
|
||||
// Created by Anthony J. Thibault on 12/17/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_SoftAttachmentModel_h
|
||||
#define hifi_SoftAttachmentModel_h
|
||||
|
||||
#include <Model.h>
|
||||
|
||||
class SoftAttachmentModel : public Model {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
SoftAttachmentModel(RigPointer rig, QObject* parent, RigPointer rigOverride);
|
||||
~SoftAttachmentModel();
|
||||
|
||||
virtual void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
||||
virtual void updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation) override;
|
||||
|
||||
protected:
|
||||
int getJointIndexOverride(int i) const;
|
||||
|
||||
RigPointer _rigOverride;
|
||||
};
|
||||
|
||||
#endif // hifi_SoftAttachmentModel_h
|
|
@ -245,6 +245,14 @@ int Rig::indexOfJoint(const QString& jointName) const {
|
|||
}
|
||||
}
|
||||
|
||||
QString Rig::nameOfJoint(int jointIndex) const {
|
||||
if (_animSkeleton) {
|
||||
return _animSkeleton->getJointName(jointIndex);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void Rig::setModelOffset(const glm::mat4& modelOffsetMat) {
|
||||
AnimPose newModelOffset = AnimPose(modelOffsetMat);
|
||||
if (!isEqual(_modelOffset.trans, newModelOffset.trans) ||
|
||||
|
|
|
@ -91,6 +91,7 @@ public:
|
|||
bool jointStatesEmpty();
|
||||
int getJointStateCount() const;
|
||||
int indexOfJoint(const QString& jointName) const;
|
||||
QString nameOfJoint(int jointIndex) const;
|
||||
|
||||
void setModelOffset(const glm::mat4& modelOffsetMat);
|
||||
|
||||
|
|
|
@ -971,11 +971,14 @@ void Model::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
_needsUpdateClusterMatrices = true;
|
||||
_rig->updateAnimations(deltaTime, parentTransform);
|
||||
}
|
||||
|
||||
void Model::simulateInternal(float deltaTime) {
|
||||
// update the world space transforms for all joints
|
||||
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset);
|
||||
updateRig(deltaTime, parentTransform);
|
||||
}
|
||||
|
||||
// virtual
|
||||
void Model::updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation) {
|
||||
PerformanceTimer perfTimer("Model::updateClusterMatrices");
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ public:
|
|||
bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; }
|
||||
|
||||
virtual void simulate(float deltaTime, bool fullUpdate = true);
|
||||
void updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation);
|
||||
virtual void updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation);
|
||||
|
||||
/// Returns a reference to the shared geometry.
|
||||
const QSharedPointer<NetworkGeometry>& getGeometry() const { return _geometry; }
|
||||
|
@ -312,7 +312,7 @@ protected:
|
|||
// hook for derived classes to be notified when setUrl invalidates the current model.
|
||||
virtual void onInvalidate() {};
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
void deleteGeometry();
|
||||
void initJointTransforms();
|
||||
|
@ -370,7 +370,6 @@ private:
|
|||
bool _showCollisionHull = false;
|
||||
|
||||
friend class ModelMeshPartPayload;
|
||||
protected:
|
||||
RigPointer _rig;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue