mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 11:17:34 +02:00
Clening up left over comments and typos, simplify the code to update Matrices in the model classes and removed renderITemsIdMap because not needed, chasing the problem of the physics objects transform
This commit is contained in:
parent
e1db1f1de2
commit
695b9cdba6
10 changed files with 125 additions and 178 deletions
|
@ -35,7 +35,6 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) {
|
||||||
std::vector<HFMCluster> dummyClustersList;
|
std::vector<HFMCluster> dummyClustersList;
|
||||||
|
|
||||||
for (int j = 0; j < defor.clusters.size(); j++) {
|
for (int j = 0; j < defor.clusters.size(); j++) {
|
||||||
std::vector<glm::mat4> bindMatrices;
|
|
||||||
// cast into a non-const reference, so we can mutate the FBXCluster
|
// cast into a non-const reference, so we can mutate the FBXCluster
|
||||||
HFMCluster& cluster = const_cast<HFMCluster&>(defor.clusters.at(j));
|
HFMCluster& cluster = const_cast<HFMCluster&>(defor.clusters.at(j));
|
||||||
|
|
||||||
|
@ -55,35 +54,6 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) {
|
||||||
}
|
}
|
||||||
_clusterBindMatrixOriginalValues.push_back(dummyClustersList);
|
_clusterBindMatrixOriginalValues.push_back(dummyClustersList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
for (int i = 0; i < (int)hfmModel.meshes.size(); i++) {
|
|
||||||
const HFMMesh& mesh = hfmModel.meshes.at(i);
|
|
||||||
std::vector<HFMCluster> dummyClustersList;
|
|
||||||
|
|
||||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
|
||||||
std::vector<glm::mat4> bindMatrices;
|
|
||||||
// cast into a non-const reference, so we can mutate the FBXCluster
|
|
||||||
HFMCluster& cluster = const_cast<HFMCluster&>(mesh.clusters.at(j));
|
|
||||||
|
|
||||||
HFMCluster localCluster;
|
|
||||||
localCluster.jointIndex = cluster.jointIndex;
|
|
||||||
localCluster.inverseBindMatrix = cluster.inverseBindMatrix;
|
|
||||||
localCluster.inverseBindTransform.evalFromRawMatrix(localCluster.inverseBindMatrix);
|
|
||||||
|
|
||||||
// if we have a joint offset in the fst file then multiply its inverse by the
|
|
||||||
// model cluster inverse bind matrix
|
|
||||||
if (hfmModel.jointRotationOffsets.contains(cluster.jointIndex)) {
|
|
||||||
AnimPose localOffset(hfmModel.jointRotationOffsets[cluster.jointIndex], glm::vec3());
|
|
||||||
localCluster.inverseBindMatrix = (glm::mat4)localOffset.inverse() * cluster.inverseBindMatrix;
|
|
||||||
localCluster.inverseBindTransform.evalFromRawMatrix(localCluster.inverseBindMatrix);
|
|
||||||
}
|
|
||||||
dummyClustersList.push_back(localCluster);
|
|
||||||
}
|
|
||||||
_clusterBindMatrixOriginalValues.push_back(dummyClustersList);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimSkeleton::AnimSkeleton(const std::vector<HFMJoint>& joints, const QMap<int, glm::quat> jointOffsets) {
|
AnimSkeleton::AnimSkeleton(const std::vector<HFMJoint>& joints, const QMap<int, glm::quat> jointOffsets) {
|
||||||
|
|
|
@ -68,9 +68,7 @@ public:
|
||||||
void dump(const AnimPoseVec& poses) const;
|
void dump(const AnimPoseVec& poses) const;
|
||||||
|
|
||||||
std::vector<int> lookUpJointIndices(const std::vector<QString>& jointNames) const;
|
std::vector<int> lookUpJointIndices(const std::vector<QString>& jointNames) const;
|
||||||
const HFMCluster getClusterBindMatricesOriginalValues(const int meshIndex, const int clusterIndex) const { return _clusterBindMatrixOriginalValues[meshIndex][clusterIndex]; }
|
const HFMCluster getClusterBindMatricesOriginalValues(const int skinDeformerIndex, const int clusterIndex) const { return _clusterBindMatrixOriginalValues[skinDeformerIndex][clusterIndex]; }
|
||||||
|
|
||||||
// const HFMCluster getClusterBindMatricesOriginalValues(const int meshIndex, const int clusterIndex) const { return _clusterBindMatrixOriginalValues[meshIndex][clusterIndex]; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void buildSkeletonFromJoints(const std::vector<HFMJoint>& joints, const QMap<int, glm::quat> jointOffsets);
|
void buildSkeletonFromJoints(const std::vector<HFMJoint>& joints, const QMap<int, glm::quat> jointOffsets);
|
||||||
|
|
|
@ -479,8 +479,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
||||||
glm::mat4 invRegistraionOffset = glm::translate(dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
|
glm::mat4 invRegistraionOffset = glm::translate(dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
|
||||||
for (uint32_t i = 0; i < numHFMMeshes; i++) {
|
for (uint32_t i = 0; i < numHFMMeshes; i++) {
|
||||||
const HFMMesh& mesh = hfmModel.meshes.at(i);
|
const HFMMesh& mesh = hfmModel.meshes.at(i);
|
||||||
if (mesh.clusters.size() > 0) {
|
if (i < hfmModel.skinDeformers.size() && hfmModel.skinDeformers[i].clusters.size() > 0) {
|
||||||
const HFMCluster& cluster = mesh.clusters.at(0);
|
const HFMCluster& cluster = hfmModel.skinDeformers[i].clusters.at(0);
|
||||||
auto jointMatrix = model->getRig().getJointTransform(cluster.jointIndex);
|
auto jointMatrix = model->getRig().getJointTransform(cluster.jointIndex);
|
||||||
// we backtranslate by the registration offset so we can apply that offset to the shapeInfo later
|
// we backtranslate by the registration offset so we can apply that offset to the shapeInfo later
|
||||||
localTransforms.push_back(invRegistraionOffset * jointMatrix * cluster.inverseBindMatrix);
|
localTransforms.push_back(invRegistraionOffset * jointMatrix * cluster.inverseBindMatrix);
|
||||||
|
|
|
@ -387,6 +387,7 @@ typedef hfm::Texture HFMTexture;
|
||||||
typedef hfm::MeshPart HFMMeshPart;
|
typedef hfm::MeshPart HFMMeshPart;
|
||||||
typedef hfm::Material HFMMaterial;
|
typedef hfm::Material HFMMaterial;
|
||||||
typedef hfm::Mesh HFMMesh;
|
typedef hfm::Mesh HFMMesh;
|
||||||
|
typedef hfm::SkinDeformer HFMSkinDeformer;
|
||||||
typedef hfm::AnimationFrame HFMAnimationFrame;
|
typedef hfm::AnimationFrame HFMAnimationFrame;
|
||||||
typedef hfm::Light HFMLight;
|
typedef hfm::Light HFMLight;
|
||||||
typedef hfm::Model HFMModel;
|
typedef hfm::Model HFMModel;
|
||||||
|
|
|
@ -33,14 +33,10 @@ bool CauterizedModel::updateGeometry() {
|
||||||
if (_isCauterized && needsFullUpdate) {
|
if (_isCauterized && needsFullUpdate) {
|
||||||
assert(_cauterizeMeshStates.empty());
|
assert(_cauterizeMeshStates.empty());
|
||||||
|
|
||||||
const HFMModel& hfmModel = getHFMModel();
|
// initialize the cauterizedDeforemrStates as a copy of the standard deformerStates
|
||||||
const auto& hfmDynamicTransforms = hfmModel.skinDeformers;
|
_cauterizeMeshStates.resize(_meshStates.size());
|
||||||
for (int i = 0; i < hfmDynamicTransforms.size(); i++) {
|
for (int i = 0; i < _meshStates.size(); ++i) {
|
||||||
const auto& dynT = hfmDynamicTransforms[i];
|
_cauterizeMeshStates[i] = _meshStates[i];
|
||||||
MeshState state;
|
|
||||||
state.clusterDualQuaternions.resize(dynT.clusters.size());
|
|
||||||
state.clusterMatrices.resize(dynT.clusters.size());
|
|
||||||
_cauterizeMeshStates.push_back(state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return needsFullUpdate;
|
return needsFullUpdate;
|
||||||
|
@ -57,7 +53,6 @@ void CauterizedModel::createRenderItemSet() {
|
||||||
|
|
||||||
_modelMeshRenderItems.clear();
|
_modelMeshRenderItems.clear();
|
||||||
_modelMeshMaterialNames.clear();
|
_modelMeshMaterialNames.clear();
|
||||||
_modelMeshRenderItemShapes.clear();
|
|
||||||
|
|
||||||
Transform transform;
|
Transform transform;
|
||||||
transform.setTranslation(_translation);
|
transform.setTranslation(_translation);
|
||||||
|
@ -79,7 +74,6 @@ void CauterizedModel::createRenderItemSet() {
|
||||||
|
|
||||||
auto material = getNetworkModel()->getShapeMaterial(shapeID);
|
auto material = getNetworkModel()->getShapeMaterial(shapeID);
|
||||||
_modelMeshMaterialNames.push_back(material ? material->getName() : "");
|
_modelMeshMaterialNames.push_back(material ? material->getName() : "");
|
||||||
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)shape.mesh, shape.skinDeformer });
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Model::createRenderItemSet();
|
Model::createRenderItemSet();
|
||||||
|
@ -97,26 +91,20 @@ void CauterizedModel::updateClusterMatrices() {
|
||||||
|
|
||||||
_needsUpdateClusterMatrices = false;
|
_needsUpdateClusterMatrices = false;
|
||||||
|
|
||||||
|
for (int skinDeformerIndex = 0; skinDeformerIndex < (int)_meshStates.size(); skinDeformerIndex++) {
|
||||||
const HFMModel& hfmModel = getHFMModel();
|
MeshState& state = _meshStates[skinDeformerIndex];
|
||||||
const auto& hfmSkinDeformers = hfmModel.skinDeformers;
|
auto numClusters = state.getNumClusters();
|
||||||
for (int meshIndex = 0; meshIndex < (int)_meshStates.size(); meshIndex++) {
|
for (uint32_t clusterIndex = 0; clusterIndex < numClusters; clusterIndex++) {
|
||||||
MeshState& state = _meshStates[meshIndex];
|
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(skinDeformerIndex, clusterIndex);
|
||||||
const auto& deformer = hfmSkinDeformers[meshIndex];
|
|
||||||
|
|
||||||
for (int clusterIndex = 0; clusterIndex < deformer.clusters.size(); clusterIndex++) {
|
|
||||||
const auto& cluster = deformer.clusters[clusterIndex];
|
|
||||||
|
|
||||||
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex);
|
|
||||||
|
|
||||||
if (_useDualQuaternionSkinning) {
|
if (_useDualQuaternionSkinning) {
|
||||||
auto jointPose = _rig.getJointPose(cluster.jointIndex);
|
auto jointPose = _rig.getJointPose(cbmov.jointIndex);
|
||||||
Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans());
|
Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans());
|
||||||
Transform clusterTransform;
|
Transform clusterTransform;
|
||||||
Transform::mult(clusterTransform, jointTransform, cbmov.inverseBindTransform);
|
Transform::mult(clusterTransform, jointTransform, cbmov.inverseBindTransform);
|
||||||
state.clusterDualQuaternions[clusterIndex] = Model::TransformDualQuaternion(clusterTransform);
|
state.clusterDualQuaternions[clusterIndex] = Model::TransformDualQuaternion(clusterTransform);
|
||||||
} else {
|
} else {
|
||||||
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
auto jointMatrix = _rig.getJointTransform(cbmov.jointIndex);
|
||||||
glm_mat4u_mul(jointMatrix, cbmov.inverseBindMatrix, state.clusterMatrices[clusterIndex]);
|
glm_mat4u_mul(jointMatrix, cbmov.inverseBindMatrix, state.clusterMatrices[clusterIndex]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,6 +115,7 @@ void CauterizedModel::updateClusterMatrices() {
|
||||||
|
|
||||||
AnimPose cauterizePose = _rig.getJointPose(_rig.indexOfJoint("Neck"));
|
AnimPose cauterizePose = _rig.getJointPose(_rig.indexOfJoint("Neck"));
|
||||||
cauterizePose.scale() = glm::vec3(0.0001f, 0.0001f, 0.0001f);
|
cauterizePose.scale() = glm::vec3(0.0001f, 0.0001f, 0.0001f);
|
||||||
|
Transform cauterizedDQTransform(cauterizePose.rot(), cauterizePose.scale(), cauterizePose.trans());
|
||||||
|
|
||||||
static const glm::mat4 zeroScale(
|
static const glm::mat4 zeroScale(
|
||||||
glm::vec4(0.0001f, 0.0f, 0.0f, 0.0f),
|
glm::vec4(0.0001f, 0.0f, 0.0f, 0.0f),
|
||||||
|
@ -135,30 +124,27 @@ void CauterizedModel::updateClusterMatrices() {
|
||||||
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
auto cauterizeMatrix = _rig.getJointTransform(_rig.indexOfJoint("Neck")) * zeroScale;
|
auto cauterizeMatrix = _rig.getJointTransform(_rig.indexOfJoint("Neck")) * zeroScale;
|
||||||
|
|
||||||
for (int meshIndex = 0; meshIndex < _cauterizeMeshStates.size(); meshIndex++) {
|
for (int skinDeformerIndex = 0; skinDeformerIndex < _cauterizeMeshStates.size(); skinDeformerIndex++) {
|
||||||
Model::MeshState& state = _cauterizeMeshStates[meshIndex];
|
Model::MeshState& nonCauterizedState = _meshStates[skinDeformerIndex];
|
||||||
const auto& deformer = hfmSkinDeformers[meshIndex];
|
Model::MeshState& state = _cauterizeMeshStates[skinDeformerIndex];
|
||||||
|
|
||||||
for (int clusterIndex = 0; clusterIndex < deformer.clusters.size(); clusterIndex++) {
|
// Just reset cauterized state with normal state memcpy style
|
||||||
const auto& cluster = deformer.clusters[clusterIndex];
|
if (_useDualQuaternionSkinning) {
|
||||||
|
state.clusterDualQuaternions = nonCauterizedState.clusterDualQuaternions;
|
||||||
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex);
|
} else {
|
||||||
|
state.clusterMatrices = nonCauterizedState.clusterMatrices;
|
||||||
if (_useDualQuaternionSkinning) {
|
}
|
||||||
if (_cauterizeBoneSet.find(cluster.jointIndex) == _cauterizeBoneSet.end()) {
|
|
||||||
// not cauterized so just copy the value from the non-cauterized version.
|
// ANd only cauterize affected joints
|
||||||
state.clusterDualQuaternions[clusterIndex] = _meshStates[meshIndex].clusterDualQuaternions[clusterIndex];
|
auto numClusters = state.getNumClusters();
|
||||||
} else {
|
for (uint32_t clusterIndex = 0; clusterIndex < numClusters; clusterIndex++) {
|
||||||
Transform jointTransform(cauterizePose.rot(), cauterizePose.scale(), cauterizePose.trans());
|
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(skinDeformerIndex, clusterIndex);
|
||||||
|
if (_cauterizeBoneSet.find(cbmov.jointIndex) != _cauterizeBoneSet.end()) {
|
||||||
|
if (_useDualQuaternionSkinning) {
|
||||||
Transform clusterTransform;
|
Transform clusterTransform;
|
||||||
Transform::mult(clusterTransform, jointTransform, cbmov.inverseBindTransform);
|
Transform::mult(clusterTransform, cauterizedDQTransform, cbmov.inverseBindTransform);
|
||||||
state.clusterDualQuaternions[clusterIndex] = Model::TransformDualQuaternion(clusterTransform);
|
state.clusterDualQuaternions[clusterIndex] = Model::TransformDualQuaternion(clusterTransform);
|
||||||
state.clusterDualQuaternions[clusterIndex].setCauterizationParameters(1.0f, cauterizePose.trans());
|
state.clusterDualQuaternions[clusterIndex].setCauterizationParameters(1.0f, cauterizePose.trans());
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (_cauterizeBoneSet.find(cluster.jointIndex) == _cauterizeBoneSet.end()) {
|
|
||||||
// not cauterized so just copy the value from the non-cauterized version.
|
|
||||||
state.clusterMatrices[clusterIndex] = _meshStates[meshIndex].clusterMatrices[clusterIndex];
|
|
||||||
} else {
|
} else {
|
||||||
glm_mat4u_mul(cauterizeMatrix, cbmov.inverseBindMatrix, state.clusterMatrices[clusterIndex]);
|
glm_mat4u_mul(cauterizeMatrix, cbmov.inverseBindMatrix, state.clusterMatrices[clusterIndex]);
|
||||||
}
|
}
|
||||||
|
@ -169,7 +155,7 @@ void CauterizedModel::updateClusterMatrices() {
|
||||||
|
|
||||||
// post the blender if we're not currently waiting for one to finish
|
// post the blender if we're not currently waiting for one to finish
|
||||||
auto modelBlender = DependencyManager::get<ModelBlender>();
|
auto modelBlender = DependencyManager::get<ModelBlender>();
|
||||||
if (modelBlender->shouldComputeBlendshapes() && hfmModel.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
|
if (modelBlender->shouldComputeBlendshapes() && getHFMModel().hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
|
||||||
_blendedBlendshapeCoefficients = _blendshapeCoefficients;
|
_blendedBlendshapeCoefficients = _blendshapeCoefficients;
|
||||||
modelBlender->noteRequiresBlend(getThisPointer());
|
modelBlender->noteRequiresBlend(getThisPointer());
|
||||||
}
|
}
|
||||||
|
@ -209,22 +195,19 @@ void CauterizedModel::updateRenderItems() {
|
||||||
|
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
for (int i = 0; i < (int)self->_modelMeshRenderItemIDs.size(); i++) {
|
for (int i = 0; i < (int)self->_modelMeshRenderItemIDs.size(); i++) {
|
||||||
|
|
||||||
auto itemID = self->_modelMeshRenderItemIDs[i];
|
auto itemID = self->_modelMeshRenderItemIDs[i];
|
||||||
auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex;
|
|
||||||
|
|
||||||
const auto& shapeState = self->getShapeState(i);
|
const auto& shapeState = self->getShapeState(i);
|
||||||
|
|
||||||
auto deformerIndex = self->_modelMeshRenderItemShapes[i].deformerIndex;
|
auto skinDeformerIndex = shapeState._skinDeformerIndex;
|
||||||
bool isDeformed = (deformerIndex != hfm::UNDEFINED_KEY);
|
|
||||||
|
|
||||||
bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex);
|
bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(shapeState._meshIndex);
|
||||||
bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning();
|
bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning();
|
||||||
|
|
||||||
if (isDeformed) {
|
if (skinDeformerIndex != hfm::UNDEFINED_KEY) {
|
||||||
|
|
||||||
const auto& meshState = self->getMeshState(deformerIndex);
|
const auto& meshState = self->getMeshState(skinDeformerIndex);
|
||||||
const auto& cauterizedMeshState = self->getCauterizeMeshState(deformerIndex);
|
const auto& cauterizedMeshState = self->getCauterizeMeshState(skinDeformerIndex);
|
||||||
|
|
||||||
transaction.updateItem<ModelMeshPartPayload>(itemID,
|
transaction.updateItem<ModelMeshPartPayload>(itemID,
|
||||||
[modelTransform, shapeState, meshState, useDualQuaternionSkinning, cauterizedMeshState, invalidatePayloadShapeKey,
|
[modelTransform, shapeState, meshState, useDualQuaternionSkinning, cauterizedMeshState, invalidatePayloadShapeKey,
|
||||||
|
|
|
@ -40,7 +40,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::unordered_set<int> _cauterizeBoneSet;
|
std::unordered_set<int> _cauterizeBoneSet;
|
||||||
QVector<Model::MeshState> _cauterizeMeshStates;
|
std::vector<Model::MeshState> _cauterizeMeshStates;
|
||||||
bool _isCauterized { false };
|
bool _isCauterized { false };
|
||||||
bool _enableCauterization { false };
|
bool _enableCauterization { false };
|
||||||
};
|
};
|
||||||
|
|
|
@ -151,7 +151,7 @@ void Model::setOffset(const glm::vec3& offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::calculateTextureInfo() {
|
void Model::calculateTextureInfo() {
|
||||||
if (!_hasCalculatedTextureInfo && isLoaded() && getNetworkModel()->areTexturesLoaded() && !_modelMeshRenderItemsMap.isEmpty()) {
|
if (!_hasCalculatedTextureInfo && isLoaded() && getNetworkModel()->areTexturesLoaded() && !_modelMeshRenderItemIDs.empty()) {
|
||||||
size_t textureSize = 0;
|
size_t textureSize = 0;
|
||||||
int textureCount = 0;
|
int textureCount = 0;
|
||||||
bool allTexturesLoaded = true;
|
bool allTexturesLoaded = true;
|
||||||
|
@ -228,25 +228,18 @@ void Model::updateRenderItems() {
|
||||||
|
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
for (int i = 0; i < (int) self->_modelMeshRenderItemIDs.size(); i++) {
|
for (int i = 0; i < (int) self->_modelMeshRenderItemIDs.size(); i++) {
|
||||||
|
|
||||||
auto itemID = self->_modelMeshRenderItemIDs[i];
|
auto itemID = self->_modelMeshRenderItemIDs[i];
|
||||||
auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex;
|
|
||||||
|
|
||||||
const auto& shapeState = self->getShapeState(i);
|
const auto& shapeState = self->getShapeState(i);
|
||||||
|
|
||||||
auto deformerIndex = self->_modelMeshRenderItemShapes[i].deformerIndex;
|
auto skinDeformerIndex = shapeState._skinDeformerIndex;
|
||||||
bool isDeformed = (deformerIndex != hfm::UNDEFINED_KEY);
|
|
||||||
|
|
||||||
bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex);
|
bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(shapeState._meshIndex);
|
||||||
|
|
||||||
|
if (skinDeformerIndex != hfm::UNDEFINED_KEY) {
|
||||||
if (isDeformed) {
|
const auto& meshState = self->getMeshState(skinDeformerIndex);
|
||||||
|
|
||||||
const auto& meshState = self->getMeshState(deformerIndex);
|
|
||||||
// MeshState meshState;
|
|
||||||
bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning();
|
bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning();
|
||||||
|
|
||||||
|
|
||||||
transaction.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, shapeState, meshState, useDualQuaternionSkinning,
|
transaction.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, shapeState, meshState, useDualQuaternionSkinning,
|
||||||
invalidatePayloadShapeKey, primitiveMode, renderItemKeyGlobalFlags, cauterized](ModelMeshPartPayload& data) {
|
invalidatePayloadShapeKey, primitiveMode, renderItemKeyGlobalFlags, cauterized](ModelMeshPartPayload& data) {
|
||||||
if (useDualQuaternionSkinning) {
|
if (useDualQuaternionSkinning) {
|
||||||
|
@ -303,15 +296,11 @@ void Model::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::updateShapeStatesFromRig() {
|
void Model::updateShapeStatesFromRig() {
|
||||||
const HFMModel& hfmModel = getHFMModel();
|
|
||||||
// TODO: should all Models have a valid _rig?
|
|
||||||
{ // Shapes state:
|
{ // Shapes state:
|
||||||
const auto& shapes = hfmModel.shapes;
|
for (auto& shape : _shapeStates) {
|
||||||
_shapeStates.resize(shapes.size());
|
uint32_t jointId = shape._jointIndex;
|
||||||
for (int s = 0; s < shapes.size(); ++s) {
|
|
||||||
uint32_t jointId = shapes[s].joint;
|
|
||||||
if (jointId < (uint32_t) _rig.getJointStateCount()) {
|
if (jointId < (uint32_t) _rig.getJointStateCount()) {
|
||||||
_shapeStates[s]._rootFromJointTransform = _rig.getJointTransform(jointId);
|
shape._rootFromJointTransform = _rig.getJointTransform(jointId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -331,9 +320,19 @@ bool Model::updateGeometry() {
|
||||||
initJointStates();
|
initJointStates();
|
||||||
assert(_meshStates.empty());
|
assert(_meshStates.empty());
|
||||||
|
|
||||||
|
const HFMModel& hfmModel = getHFMModel();
|
||||||
|
|
||||||
|
const auto& shapes = hfmModel.shapes;
|
||||||
|
_shapeStates.resize(shapes.size());
|
||||||
|
for (int s = 0; s < shapes.size(); ++s) {
|
||||||
|
auto& shapeState = _shapeStates[s];
|
||||||
|
shapeState._jointIndex = shapes[s].joint;
|
||||||
|
shapeState._meshIndex = shapes[s].mesh;
|
||||||
|
shapeState._meshPartIndex = shapes[s].meshPart;
|
||||||
|
shapeState._skinDeformerIndex = shapes[s].skinDeformer;
|
||||||
|
}
|
||||||
updateShapeStatesFromRig();
|
updateShapeStatesFromRig();
|
||||||
|
|
||||||
const HFMModel& hfmModel = getHFMModel();
|
|
||||||
const auto& hfmSkinDeformers = hfmModel.skinDeformers;
|
const auto& hfmSkinDeformers = hfmModel.skinDeformers;
|
||||||
for (int i = 0; i < hfmSkinDeformers.size(); i++) {
|
for (int i = 0; i < hfmSkinDeformers.size(); i++) {
|
||||||
const auto& dynT = hfmSkinDeformers[i];
|
const auto& dynT = hfmSkinDeformers[i];
|
||||||
|
@ -740,9 +739,9 @@ bool Model::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointe
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
for (int i = 0; i < (int) _modelMeshRenderItemIDs.size(); i++) {
|
for (int i = 0; i < (int) _modelMeshRenderItemIDs.size(); i++) {
|
||||||
auto itemID = _modelMeshRenderItemIDs[i];
|
auto itemID = _modelMeshRenderItemIDs[i];
|
||||||
auto shape = _modelMeshRenderItemShapes[i];
|
auto& shape = _shapeStates[i];
|
||||||
// TODO: check to see if .partIndex matches too
|
// TODO: check to see if .partIndex matches too
|
||||||
if (shape.meshIndex == meshIndex) {
|
if (shape._meshIndex == meshIndex) {
|
||||||
transaction.updateItem<ModelMeshPartPayload>(itemID, [=](ModelMeshPartPayload& data) {
|
transaction.updateItem<ModelMeshPartPayload>(itemID, [=](ModelMeshPartPayload& data) {
|
||||||
data.updateMeshPart(mesh, partIndex);
|
data.updateMeshPart(mesh, partIndex);
|
||||||
});
|
});
|
||||||
|
@ -904,8 +903,8 @@ void Model::updateRenderItemsKey(const render::ScenePointer& scene) {
|
||||||
}
|
}
|
||||||
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
foreach(auto item, _modelMeshRenderItemsMap.keys()) {
|
for(auto itemID: _modelMeshRenderItemIDs) {
|
||||||
transaction.updateItem<ModelMeshPartPayload>(item, [renderItemsKey](ModelMeshPartPayload& data) {
|
transaction.updateItem<ModelMeshPartPayload>(itemID, [renderItemsKey](ModelMeshPartPayload& data) {
|
||||||
data.updateKey(renderItemsKey);
|
data.updateKey(renderItemsKey);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -975,8 +974,8 @@ void Model::setCauterized(bool cauterized, const render::ScenePointer& scene) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
foreach (auto item, _modelMeshRenderItemsMap.keys()) {
|
for (auto itemID : _modelMeshRenderItemIDs) {
|
||||||
transaction.updateItem<ModelMeshPartPayload>(item, [cauterized](ModelMeshPartPayload& data) {
|
transaction.updateItem<ModelMeshPartPayload>(itemID, [cauterized](ModelMeshPartPayload& data) {
|
||||||
data.setCauterized(cauterized);
|
data.setCauterized(cauterized);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1003,26 +1002,25 @@ bool Model::addToScene(const render::ScenePointer& scene,
|
||||||
|
|
||||||
bool somethingAdded = false;
|
bool somethingAdded = false;
|
||||||
|
|
||||||
if (_modelMeshRenderItemsMap.empty()) {
|
if (_modelMeshRenderItemIDs.empty()) {
|
||||||
bool hasTransparent = false;
|
bool hasTransparent = false;
|
||||||
size_t verticesCount = 0;
|
size_t verticesCount = 0;
|
||||||
foreach(auto renderItem, _modelMeshRenderItems) {
|
foreach(auto renderItem, _modelMeshRenderItems) {
|
||||||
auto item = scene->allocateID();
|
auto item = scene->allocateID();
|
||||||
auto renderPayload = std::make_shared<ModelMeshPartPayload::Payload>(renderItem);
|
auto renderPayload = std::make_shared<ModelMeshPartPayload::Payload>(renderItem);
|
||||||
if (_modelMeshRenderItemsMap.empty() && statusGetters.size()) {
|
if (_modelMeshRenderItemIDs.empty() && statusGetters.size()) {
|
||||||
renderPayload->addStatusGetters(statusGetters);
|
renderPayload->addStatusGetters(statusGetters);
|
||||||
}
|
}
|
||||||
transaction.resetItem(item, renderPayload);
|
transaction.resetItem(item, renderPayload);
|
||||||
|
|
||||||
hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent();
|
hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent();
|
||||||
verticesCount += renderItem.get()->getVerticesCount();
|
verticesCount += renderItem.get()->getVerticesCount();
|
||||||
_modelMeshRenderItemsMap.insert(item, renderPayload);
|
|
||||||
_modelMeshRenderItemIDs.emplace_back(item);
|
_modelMeshRenderItemIDs.emplace_back(item);
|
||||||
}
|
}
|
||||||
somethingAdded = !_modelMeshRenderItemsMap.empty();
|
somethingAdded = !_modelMeshRenderItemIDs.empty();
|
||||||
|
|
||||||
_renderInfoVertexCount = verticesCount;
|
_renderInfoVertexCount = verticesCount;
|
||||||
_renderInfoDrawCalls = _modelMeshRenderItemsMap.count();
|
_renderInfoDrawCalls = (uint32_t) _modelMeshRenderItemIDs.size();
|
||||||
_renderInfoHasTransparent = hasTransparent;
|
_renderInfoHasTransparent = hasTransparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1037,14 +1035,12 @@ bool Model::addToScene(const render::ScenePointer& scene,
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::removeFromScene(const render::ScenePointer& scene, render::Transaction& transaction) {
|
void Model::removeFromScene(const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||||
foreach (auto item, _modelMeshRenderItemsMap.keys()) {
|
for (auto itemID: _modelMeshRenderItemIDs) {
|
||||||
transaction.removeItem(item);
|
transaction.removeItem(itemID);
|
||||||
}
|
}
|
||||||
_modelMeshRenderItemIDs.clear();
|
_modelMeshRenderItemIDs.clear();
|
||||||
_modelMeshRenderItemsMap.clear();
|
|
||||||
_modelMeshRenderItems.clear();
|
_modelMeshRenderItems.clear();
|
||||||
_modelMeshMaterialNames.clear();
|
_modelMeshMaterialNames.clear();
|
||||||
_modelMeshRenderItemShapes.clear();
|
|
||||||
_priorityMap.clear();
|
_priorityMap.clear();
|
||||||
|
|
||||||
_addedToScene = false;
|
_addedToScene = false;
|
||||||
|
@ -1415,25 +1411,22 @@ void Model::updateClusterMatrices() {
|
||||||
updateShapeStatesFromRig();
|
updateShapeStatesFromRig();
|
||||||
|
|
||||||
_needsUpdateClusterMatrices = false;
|
_needsUpdateClusterMatrices = false;
|
||||||
const HFMModel& hfmModel = getHFMModel();
|
|
||||||
const auto& hfmSkinDeformers = hfmModel.skinDeformers;
|
|
||||||
for (int meshIndex = 0; meshIndex < (int) _meshStates.size(); meshIndex++) {
|
|
||||||
MeshState& state = _meshStates[meshIndex];
|
|
||||||
const auto& deformer = hfmSkinDeformers[meshIndex];
|
|
||||||
|
|
||||||
for (int clusterIndex = 0; clusterIndex < deformer.clusters.size(); clusterIndex++) {
|
for (int skinDeformerIndex = 0; skinDeformerIndex < (int)_meshStates.size(); skinDeformerIndex++) {
|
||||||
const auto& cluster = deformer.clusters[clusterIndex];
|
MeshState& state = _meshStates[skinDeformerIndex];
|
||||||
|
auto numClusters = state.getNumClusters();
|
||||||
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex);
|
for (uint32_t clusterIndex = 0; clusterIndex < numClusters; clusterIndex++) {
|
||||||
|
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(skinDeformerIndex, clusterIndex);
|
||||||
|
|
||||||
if (_useDualQuaternionSkinning) {
|
if (_useDualQuaternionSkinning) {
|
||||||
auto jointPose = _rig.getJointPose(cluster.jointIndex);
|
auto jointPose = _rig.getJointPose(cbmov.jointIndex);
|
||||||
Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans());
|
Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans());
|
||||||
Transform clusterTransform;
|
Transform clusterTransform;
|
||||||
Transform::mult(clusterTransform, jointTransform, cbmov.inverseBindTransform);
|
Transform::mult(clusterTransform, jointTransform, cbmov.inverseBindTransform);
|
||||||
state.clusterDualQuaternions[clusterIndex] = Model::TransformDualQuaternion(clusterTransform);
|
state.clusterDualQuaternions[clusterIndex] = Model::TransformDualQuaternion(clusterTransform);
|
||||||
} else {
|
}
|
||||||
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
else {
|
||||||
|
auto jointMatrix = _rig.getJointTransform(cbmov.jointIndex);
|
||||||
glm_mat4u_mul(jointMatrix, cbmov.inverseBindMatrix, state.clusterMatrices[clusterIndex]);
|
glm_mat4u_mul(jointMatrix, cbmov.inverseBindMatrix, state.clusterMatrices[clusterIndex]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1441,7 +1434,7 @@ void Model::updateClusterMatrices() {
|
||||||
|
|
||||||
// post the blender if we're not currently waiting for one to finish
|
// post the blender if we're not currently waiting for one to finish
|
||||||
auto modelBlender = DependencyManager::get<ModelBlender>();
|
auto modelBlender = DependencyManager::get<ModelBlender>();
|
||||||
if (modelBlender->shouldComputeBlendshapes() && hfmModel.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
|
if (modelBlender->shouldComputeBlendshapes() && getHFMModel().hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
|
||||||
_blendedBlendshapeCoefficients = _blendshapeCoefficients;
|
_blendedBlendshapeCoefficients = _blendshapeCoefficients;
|
||||||
modelBlender->noteRequiresBlend(getThisPointer());
|
modelBlender->noteRequiresBlend(getThisPointer());
|
||||||
}
|
}
|
||||||
|
@ -1490,7 +1483,6 @@ void Model::createRenderItemSet() {
|
||||||
|
|
||||||
_modelMeshRenderItems.clear();
|
_modelMeshRenderItems.clear();
|
||||||
_modelMeshMaterialNames.clear();
|
_modelMeshMaterialNames.clear();
|
||||||
_modelMeshRenderItemShapes.clear();
|
|
||||||
|
|
||||||
Transform transform;
|
Transform transform;
|
||||||
transform.setTranslation(_translation);
|
transform.setTranslation(_translation);
|
||||||
|
@ -1510,12 +1502,11 @@ void Model::createRenderItemSet() {
|
||||||
|
|
||||||
auto material = getNetworkModel()->getShapeMaterial(shapeID);
|
auto material = getNetworkModel()->getShapeMaterial(shapeID);
|
||||||
_modelMeshMaterialNames.push_back(material ? material->getName() : "");
|
_modelMeshMaterialNames.push_back(material ? material->getName() : "");
|
||||||
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)shape.mesh, shape.skinDeformer });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::isRenderable() const {
|
bool Model::isRenderable() const {
|
||||||
return (!_shapeStates.empty() /* && !_meshStates.empty()*/) || (isLoaded() && _renderGeometry->getMeshes().empty());
|
return (!_shapeStates.empty()) || (isLoaded() && _renderGeometry->getMeshes().empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<unsigned int> Model::getMeshIDsFromMaterialID(QString parentMaterialName) {
|
std::set<unsigned int> Model::getMeshIDsFromMaterialID(QString parentMaterialName) {
|
||||||
|
@ -1571,11 +1562,11 @@ void Model::applyMaterialMapping() {
|
||||||
PrimitiveMode primitiveMode = getPrimitiveMode();
|
PrimitiveMode primitiveMode = getPrimitiveMode();
|
||||||
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
|
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
|
||||||
auto modelMeshRenderItemIDs = _modelMeshRenderItemIDs;
|
auto modelMeshRenderItemIDs = _modelMeshRenderItemIDs;
|
||||||
auto modelMeshRenderItemShapes = _modelMeshRenderItemShapes;
|
auto shapeStates = _shapeStates;
|
||||||
std::unordered_map<int, bool> shouldInvalidatePayloadShapeKeyMap;
|
std::unordered_map<int, bool> shouldInvalidatePayloadShapeKeyMap;
|
||||||
|
|
||||||
for (auto& shape : _modelMeshRenderItemShapes) {
|
for (auto& shape : _shapeStates) {
|
||||||
shouldInvalidatePayloadShapeKeyMap[shape.meshIndex] = shouldInvalidatePayloadShapeKey(shape.meshIndex);
|
shouldInvalidatePayloadShapeKeyMap[shape._meshIndex] = shouldInvalidatePayloadShapeKey(shape._meshIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& materialMapping = getMaterialMapping();
|
auto& materialMapping = getMaterialMapping();
|
||||||
|
@ -1598,7 +1589,7 @@ void Model::applyMaterialMapping() {
|
||||||
|
|
||||||
std::weak_ptr<Model> weakSelf = shared_from_this();
|
std::weak_ptr<Model> weakSelf = shared_from_this();
|
||||||
auto materialLoaded = [networkMaterialResource, shapeIDs, priorityMapPerResource, renderItemsKey, primitiveMode, useDualQuaternionSkinning,
|
auto materialLoaded = [networkMaterialResource, shapeIDs, priorityMapPerResource, renderItemsKey, primitiveMode, useDualQuaternionSkinning,
|
||||||
modelMeshRenderItemIDs, modelMeshRenderItemShapes, shouldInvalidatePayloadShapeKeyMap, weakSelf]() {
|
modelMeshRenderItemIDs, shapeStates, shouldInvalidatePayloadShapeKeyMap, weakSelf]() {
|
||||||
std::shared_ptr<Model> self = weakSelf.lock();
|
std::shared_ptr<Model> self = weakSelf.lock();
|
||||||
if (!self || networkMaterialResource->isFailed() || networkMaterialResource->parsedMaterials.names.size() == 0) {
|
if (!self || networkMaterialResource->isFailed() || networkMaterialResource->parsedMaterials.names.size() == 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -1624,7 +1615,7 @@ void Model::applyMaterialMapping() {
|
||||||
for (auto shapeID : shapeIDs) {
|
for (auto shapeID : shapeIDs) {
|
||||||
if (shapeID < modelMeshRenderItemIDs.size()) {
|
if (shapeID < modelMeshRenderItemIDs.size()) {
|
||||||
auto itemID = modelMeshRenderItemIDs[shapeID];
|
auto itemID = modelMeshRenderItemIDs[shapeID];
|
||||||
auto meshIndex = modelMeshRenderItemShapes[shapeID].meshIndex;
|
auto meshIndex = shapeStates[shapeID]._meshIndex;
|
||||||
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKeyMap.at(meshIndex);
|
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKeyMap.at(meshIndex);
|
||||||
graphics::MaterialLayer material = graphics::MaterialLayer(networkMaterial, priorityMapPerResource.at(shapeID));
|
graphics::MaterialLayer material = graphics::MaterialLayer(networkMaterial, priorityMapPerResource.at(shapeID));
|
||||||
{
|
{
|
||||||
|
@ -1662,7 +1653,7 @@ void Model::addMaterial(graphics::MaterialLayer material, const std::string& par
|
||||||
for (auto shapeID : shapeIDs) {
|
for (auto shapeID : shapeIDs) {
|
||||||
if (shapeID < _modelMeshRenderItemIDs.size()) {
|
if (shapeID < _modelMeshRenderItemIDs.size()) {
|
||||||
auto itemID = _modelMeshRenderItemIDs[shapeID];
|
auto itemID = _modelMeshRenderItemIDs[shapeID];
|
||||||
auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex;
|
auto meshIndex = _shapeStates[shapeID]._meshIndex;
|
||||||
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
||||||
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, renderItemsKey,
|
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, renderItemsKey,
|
||||||
invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning](ModelMeshPartPayload& data) {
|
invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning](ModelMeshPartPayload& data) {
|
||||||
|
@ -1684,7 +1675,7 @@ void Model::removeMaterial(graphics::MaterialPointer material, const std::string
|
||||||
auto itemID = _modelMeshRenderItemIDs[shapeID];
|
auto itemID = _modelMeshRenderItemIDs[shapeID];
|
||||||
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
||||||
PrimitiveMode primitiveMode = getPrimitiveMode();
|
PrimitiveMode primitiveMode = getPrimitiveMode();
|
||||||
auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex;
|
auto meshIndex = _shapeStates[shapeID]._meshIndex;
|
||||||
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
||||||
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
|
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
|
||||||
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, renderItemsKey,
|
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, renderItemsKey,
|
||||||
|
|
|
@ -297,6 +297,16 @@ public:
|
||||||
int getRenderInfoDrawCalls() const { return _renderInfoDrawCalls; }
|
int getRenderInfoDrawCalls() const { return _renderInfoDrawCalls; }
|
||||||
bool getRenderInfoHasTransparent() const { return _renderInfoHasTransparent; }
|
bool getRenderInfoHasTransparent() const { return _renderInfoHasTransparent; }
|
||||||
|
|
||||||
|
class ShapeState {
|
||||||
|
public:
|
||||||
|
glm::mat4 _rootFromJointTransform;
|
||||||
|
uint32_t _jointIndex{ hfm::UNDEFINED_KEY };
|
||||||
|
uint32_t _meshIndex{ hfm::UNDEFINED_KEY };
|
||||||
|
uint32_t _meshPartIndex{ hfm::UNDEFINED_KEY };
|
||||||
|
uint32_t _skinDeformerIndex{ hfm::UNDEFINED_KEY };
|
||||||
|
};
|
||||||
|
const ShapeState& getShapeState(int index) { return _shapeStates.at(index); }
|
||||||
|
|
||||||
class TransformDualQuaternion {
|
class TransformDualQuaternion {
|
||||||
public:
|
public:
|
||||||
TransformDualQuaternion() {}
|
TransformDualQuaternion() {}
|
||||||
|
@ -339,18 +349,13 @@ public:
|
||||||
public:
|
public:
|
||||||
std::vector<TransformDualQuaternion> clusterDualQuaternions;
|
std::vector<TransformDualQuaternion> clusterDualQuaternions;
|
||||||
std::vector<glm::mat4> clusterMatrices;
|
std::vector<glm::mat4> clusterMatrices;
|
||||||
};
|
|
||||||
|
|
||||||
|
uint32_t getNumClusters() const { return (uint32_t) std::max(clusterMatrices.size(), clusterMatrices.size()); }
|
||||||
|
};
|
||||||
const MeshState& getMeshState(int index) { return _meshStates.at(index); }
|
const MeshState& getMeshState(int index) { return _meshStates.at(index); }
|
||||||
|
|
||||||
class ShapeState {
|
|
||||||
public:
|
|
||||||
glm::mat4 _rootFromJointTransform;
|
|
||||||
};
|
|
||||||
const ShapeState& getShapeState(int index) { return _shapeStates.at(index); }
|
|
||||||
|
|
||||||
uint32_t getGeometryCounter() const { return _deleteGeometryCounter; }
|
uint32_t getGeometryCounter() const { return _deleteGeometryCounter; }
|
||||||
const QMap<render::ItemID, render::PayloadPointer>& getRenderItems() const { return _modelMeshRenderItemsMap; }
|
|
||||||
BlendShapeOperator getModelBlendshapeOperator() const { return _modelBlendshapeOperator; }
|
BlendShapeOperator getModelBlendshapeOperator() const { return _modelBlendshapeOperator; }
|
||||||
|
|
||||||
void renderDebugMeshBoxes(gpu::Batch& batch, bool forward);
|
void renderDebugMeshBoxes(gpu::Batch& batch, bool forward);
|
||||||
|
@ -425,10 +430,12 @@ protected:
|
||||||
bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point
|
bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point
|
||||||
glm::vec3 _registrationPoint = glm::vec3(0.5f); /// the point in model space our center is snapped to
|
glm::vec3 _registrationPoint = glm::vec3(0.5f); /// the point in model space our center is snapped to
|
||||||
|
|
||||||
std::vector<MeshState> _meshStates;
|
|
||||||
std::vector<ShapeState> _shapeStates;
|
std::vector<ShapeState> _shapeStates;
|
||||||
void updateShapeStatesFromRig();
|
void updateShapeStatesFromRig();
|
||||||
|
|
||||||
|
std::vector<MeshState> _meshStates;
|
||||||
|
|
||||||
virtual void initJointStates();
|
virtual void initJointStates();
|
||||||
|
|
||||||
void setScaleInternal(const glm::vec3& scale);
|
void setScaleInternal(const glm::vec3& scale);
|
||||||
|
@ -471,10 +478,7 @@ protected:
|
||||||
static AbstractViewStateInterface* _viewState;
|
static AbstractViewStateInterface* _viewState;
|
||||||
|
|
||||||
QVector<std::shared_ptr<ModelMeshPartPayload>> _modelMeshRenderItems;
|
QVector<std::shared_ptr<ModelMeshPartPayload>> _modelMeshRenderItems;
|
||||||
QMap<render::ItemID, render::PayloadPointer> _modelMeshRenderItemsMap;
|
|
||||||
render::ItemIDs _modelMeshRenderItemIDs;
|
render::ItemIDs _modelMeshRenderItemIDs;
|
||||||
using ShapeInfo = struct { int meshIndex; uint32_t deformerIndex{ hfm::UNDEFINED_KEY }; };
|
|
||||||
std::vector<ShapeInfo> _modelMeshRenderItemShapes;
|
|
||||||
std::vector<std::string> _modelMeshMaterialNames;
|
std::vector<std::string> _modelMeshMaterialNames;
|
||||||
|
|
||||||
bool _addedToScene { false }; // has been added to scene
|
bool _addedToScene { false }; // has been added to scene
|
||||||
|
|
|
@ -41,37 +41,37 @@ void SoftAttachmentModel::updateClusterMatrices() {
|
||||||
|
|
||||||
_needsUpdateClusterMatrices = false;
|
_needsUpdateClusterMatrices = false;
|
||||||
|
|
||||||
const HFMModel& hfmModel = getHFMModel();
|
|
||||||
|
|
||||||
for (int i = 0; i < (int) _meshStates.size(); i++) {
|
for (int skinDeformerIndex = 0; skinDeformerIndex < (int)_meshStates.size(); skinDeformerIndex++) {
|
||||||
MeshState& state = _meshStates[i];
|
MeshState& state = _meshStates[skinDeformerIndex];
|
||||||
const HFMMesh& mesh = hfmModel.meshes.at(i);
|
auto numClusters = state.getNumClusters();
|
||||||
int meshIndex = i;
|
for (uint32_t clusterIndex = 0; clusterIndex < numClusters; clusterIndex++) {
|
||||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(skinDeformerIndex, clusterIndex);
|
||||||
const HFMCluster& cluster = mesh.clusters.at(j);
|
|
||||||
|
|
||||||
int clusterIndex = j;
|
|
||||||
// TODO: cache these look-ups as an optimization
|
// TODO: cache these look-ups as an optimization
|
||||||
int jointIndexOverride = getJointIndexOverride(cluster.jointIndex);
|
int jointIndexOverride = getJointIndexOverride(cbmov.jointIndex);
|
||||||
glm::mat4 jointMatrix;
|
auto rig = &_rigOverride;
|
||||||
if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) {
|
if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) {
|
||||||
jointMatrix = _rigOverride.getJointTransform(jointIndexOverride);
|
rig = &_rig;
|
||||||
} else {
|
|
||||||
jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_useDualQuaternionSkinning) {
|
if (_useDualQuaternionSkinning) {
|
||||||
glm::mat4 m;
|
auto jointPose = rig->getJointPose(cbmov.jointIndex);
|
||||||
glm_mat4u_mul(jointMatrix, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindMatrix, m);
|
Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans());
|
||||||
state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(m);
|
Transform clusterTransform;
|
||||||
} else {
|
Transform::mult(clusterTransform, jointTransform, cbmov.inverseBindTransform);
|
||||||
glm_mat4u_mul(jointMatrix, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindMatrix, state.clusterMatrices[j]);
|
state.clusterDualQuaternions[clusterIndex] = Model::TransformDualQuaternion(clusterTransform);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto jointMatrix = rig->getJointTransform(cbmov.jointIndex);
|
||||||
|
glm_mat4u_mul(jointMatrix, cbmov.inverseBindMatrix, state.clusterMatrices[clusterIndex]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// post the blender if we're not currently waiting for one to finish
|
// post the blender if we're not currently waiting for one to finish
|
||||||
auto modelBlender = DependencyManager::get<ModelBlender>();
|
auto modelBlender = DependencyManager::get<ModelBlender>();
|
||||||
if (modelBlender->shouldComputeBlendshapes() && hfmModel.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
|
if (modelBlender->shouldComputeBlendshapes() && getHFMModel().hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
|
||||||
_blendedBlendshapeCoefficients = _blendshapeCoefficients;
|
_blendedBlendshapeCoefficients = _blendshapeCoefficients;
|
||||||
modelBlender->noteRequiresBlend(getThisPointer());
|
modelBlender->noteRequiresBlend(getThisPointer());
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,7 +348,7 @@ bool vhacd::VHACDUtil::computeVHACD(HFMModel& hfmModel,
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
qDebug() << "mesh" << meshIndex << ": "
|
qDebug() << "mesh" << meshIndex << ": "
|
||||||
<< " parts =" << mesh.parts.size() << " clusters =" << mesh.clusters.size()
|
<< " parts =" << mesh.parts.size()
|
||||||
<< " vertices =" << numVertices;
|
<< " vertices =" << numVertices;
|
||||||
}
|
}
|
||||||
++meshIndex;
|
++meshIndex;
|
||||||
|
|
Loading…
Reference in a new issue