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:
Sam Gateau 2019-10-18 03:31:06 -07:00
parent e1db1f1de2
commit 695b9cdba6
10 changed files with 125 additions and 178 deletions

View file

@ -35,7 +35,6 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) {
std::vector<HFMCluster> dummyClustersList;
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
HFMCluster& cluster = const_cast<HFMCluster&>(defor.clusters.at(j));
@ -55,35 +54,6 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) {
}
_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) {

View file

@ -68,9 +68,7 @@ public:
void dump(const AnimPoseVec& poses) 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 meshIndex, const int clusterIndex) const { return _clusterBindMatrixOriginalValues[meshIndex][clusterIndex]; }
const HFMCluster getClusterBindMatricesOriginalValues(const int skinDeformerIndex, const int clusterIndex) const { return _clusterBindMatrixOriginalValues[skinDeformerIndex][clusterIndex]; }
protected:
void buildSkeletonFromJoints(const std::vector<HFMJoint>& joints, const QMap<int, glm::quat> jointOffsets);

View file

@ -479,8 +479,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
glm::mat4 invRegistraionOffset = glm::translate(dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
for (uint32_t i = 0; i < numHFMMeshes; i++) {
const HFMMesh& mesh = hfmModel.meshes.at(i);
if (mesh.clusters.size() > 0) {
const HFMCluster& cluster = mesh.clusters.at(0);
if (i < hfmModel.skinDeformers.size() && hfmModel.skinDeformers[i].clusters.size() > 0) {
const HFMCluster& cluster = hfmModel.skinDeformers[i].clusters.at(0);
auto jointMatrix = model->getRig().getJointTransform(cluster.jointIndex);
// we backtranslate by the registration offset so we can apply that offset to the shapeInfo later
localTransforms.push_back(invRegistraionOffset * jointMatrix * cluster.inverseBindMatrix);

View file

@ -387,6 +387,7 @@ typedef hfm::Texture HFMTexture;
typedef hfm::MeshPart HFMMeshPart;
typedef hfm::Material HFMMaterial;
typedef hfm::Mesh HFMMesh;
typedef hfm::SkinDeformer HFMSkinDeformer;
typedef hfm::AnimationFrame HFMAnimationFrame;
typedef hfm::Light HFMLight;
typedef hfm::Model HFMModel;

View file

@ -33,14 +33,10 @@ bool CauterizedModel::updateGeometry() {
if (_isCauterized && needsFullUpdate) {
assert(_cauterizeMeshStates.empty());
const HFMModel& hfmModel = getHFMModel();
const auto& hfmDynamicTransforms = hfmModel.skinDeformers;
for (int i = 0; i < hfmDynamicTransforms.size(); i++) {
const auto& dynT = hfmDynamicTransforms[i];
MeshState state;
state.clusterDualQuaternions.resize(dynT.clusters.size());
state.clusterMatrices.resize(dynT.clusters.size());
_cauterizeMeshStates.push_back(state);
// initialize the cauterizedDeforemrStates as a copy of the standard deformerStates
_cauterizeMeshStates.resize(_meshStates.size());
for (int i = 0; i < _meshStates.size(); ++i) {
_cauterizeMeshStates[i] = _meshStates[i];
}
}
return needsFullUpdate;
@ -57,7 +53,6 @@ void CauterizedModel::createRenderItemSet() {
_modelMeshRenderItems.clear();
_modelMeshMaterialNames.clear();
_modelMeshRenderItemShapes.clear();
Transform transform;
transform.setTranslation(_translation);
@ -79,7 +74,6 @@ void CauterizedModel::createRenderItemSet() {
auto material = getNetworkModel()->getShapeMaterial(shapeID);
_modelMeshMaterialNames.push_back(material ? material->getName() : "");
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)shape.mesh, shape.skinDeformer });
}
} else {
Model::createRenderItemSet();
@ -97,26 +91,20 @@ void CauterizedModel::updateClusterMatrices() {
_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++) {
const auto& cluster = deformer.clusters[clusterIndex];
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex);
for (int skinDeformerIndex = 0; skinDeformerIndex < (int)_meshStates.size(); skinDeformerIndex++) {
MeshState& state = _meshStates[skinDeformerIndex];
auto numClusters = state.getNumClusters();
for (uint32_t clusterIndex = 0; clusterIndex < numClusters; clusterIndex++) {
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(skinDeformerIndex, clusterIndex);
if (_useDualQuaternionSkinning) {
auto jointPose = _rig.getJointPose(cluster.jointIndex);
auto jointPose = _rig.getJointPose(cbmov.jointIndex);
Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans());
Transform clusterTransform;
Transform::mult(clusterTransform, jointTransform, cbmov.inverseBindTransform);
state.clusterDualQuaternions[clusterIndex] = Model::TransformDualQuaternion(clusterTransform);
} else {
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
auto jointMatrix = _rig.getJointTransform(cbmov.jointIndex);
glm_mat4u_mul(jointMatrix, cbmov.inverseBindMatrix, state.clusterMatrices[clusterIndex]);
}
}
@ -127,6 +115,7 @@ void CauterizedModel::updateClusterMatrices() {
AnimPose cauterizePose = _rig.getJointPose(_rig.indexOfJoint("Neck"));
cauterizePose.scale() = glm::vec3(0.0001f, 0.0001f, 0.0001f);
Transform cauterizedDQTransform(cauterizePose.rot(), cauterizePose.scale(), cauterizePose.trans());
static const glm::mat4 zeroScale(
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));
auto cauterizeMatrix = _rig.getJointTransform(_rig.indexOfJoint("Neck")) * zeroScale;
for (int meshIndex = 0; meshIndex < _cauterizeMeshStates.size(); meshIndex++) {
Model::MeshState& state = _cauterizeMeshStates[meshIndex];
const auto& deformer = hfmSkinDeformers[meshIndex];
for (int skinDeformerIndex = 0; skinDeformerIndex < _cauterizeMeshStates.size(); skinDeformerIndex++) {
Model::MeshState& nonCauterizedState = _meshStates[skinDeformerIndex];
Model::MeshState& state = _cauterizeMeshStates[skinDeformerIndex];
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 (_cauterizeBoneSet.find(cluster.jointIndex) == _cauterizeBoneSet.end()) {
// not cauterized so just copy the value from the non-cauterized version.
state.clusterDualQuaternions[clusterIndex] = _meshStates[meshIndex].clusterDualQuaternions[clusterIndex];
} else {
Transform jointTransform(cauterizePose.rot(), cauterizePose.scale(), cauterizePose.trans());
// Just reset cauterized state with normal state memcpy style
if (_useDualQuaternionSkinning) {
state.clusterDualQuaternions = nonCauterizedState.clusterDualQuaternions;
} else {
state.clusterMatrices = nonCauterizedState.clusterMatrices;
}
// ANd only cauterize affected joints
auto numClusters = state.getNumClusters();
for (uint32_t clusterIndex = 0; clusterIndex < numClusters; clusterIndex++) {
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(skinDeformerIndex, clusterIndex);
if (_cauterizeBoneSet.find(cbmov.jointIndex) != _cauterizeBoneSet.end()) {
if (_useDualQuaternionSkinning) {
Transform clusterTransform;
Transform::mult(clusterTransform, jointTransform, cbmov.inverseBindTransform);
Transform::mult(clusterTransform, cauterizedDQTransform, cbmov.inverseBindTransform);
state.clusterDualQuaternions[clusterIndex] = Model::TransformDualQuaternion(clusterTransform);
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 {
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
auto modelBlender = DependencyManager::get<ModelBlender>();
if (modelBlender->shouldComputeBlendshapes() && hfmModel.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
if (modelBlender->shouldComputeBlendshapes() && getHFMModel().hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
_blendedBlendshapeCoefficients = _blendshapeCoefficients;
modelBlender->noteRequiresBlend(getThisPointer());
}
@ -209,22 +195,19 @@ void CauterizedModel::updateRenderItems() {
render::Transaction transaction;
for (int i = 0; i < (int)self->_modelMeshRenderItemIDs.size(); i++) {
auto itemID = self->_modelMeshRenderItemIDs[i];
auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex;
const auto& shapeState = self->getShapeState(i);
auto deformerIndex = self->_modelMeshRenderItemShapes[i].deformerIndex;
bool isDeformed = (deformerIndex != hfm::UNDEFINED_KEY);
auto skinDeformerIndex = shapeState._skinDeformerIndex;
bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex);
bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(shapeState._meshIndex);
bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning();
if (isDeformed) {
if (skinDeformerIndex != hfm::UNDEFINED_KEY) {
const auto& meshState = self->getMeshState(deformerIndex);
const auto& cauterizedMeshState = self->getCauterizeMeshState(deformerIndex);
const auto& meshState = self->getMeshState(skinDeformerIndex);
const auto& cauterizedMeshState = self->getCauterizeMeshState(skinDeformerIndex);
transaction.updateItem<ModelMeshPartPayload>(itemID,
[modelTransform, shapeState, meshState, useDualQuaternionSkinning, cauterizedMeshState, invalidatePayloadShapeKey,

View file

@ -40,7 +40,7 @@ public:
protected:
std::unordered_set<int> _cauterizeBoneSet;
QVector<Model::MeshState> _cauterizeMeshStates;
std::vector<Model::MeshState> _cauterizeMeshStates;
bool _isCauterized { false };
bool _enableCauterization { false };
};

View file

@ -151,7 +151,7 @@ void Model::setOffset(const glm::vec3& offset) {
}
void Model::calculateTextureInfo() {
if (!_hasCalculatedTextureInfo && isLoaded() && getNetworkModel()->areTexturesLoaded() && !_modelMeshRenderItemsMap.isEmpty()) {
if (!_hasCalculatedTextureInfo && isLoaded() && getNetworkModel()->areTexturesLoaded() && !_modelMeshRenderItemIDs.empty()) {
size_t textureSize = 0;
int textureCount = 0;
bool allTexturesLoaded = true;
@ -228,25 +228,18 @@ void Model::updateRenderItems() {
render::Transaction transaction;
for (int i = 0; i < (int) self->_modelMeshRenderItemIDs.size(); i++) {
auto itemID = self->_modelMeshRenderItemIDs[i];
auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex;
const auto& shapeState = self->getShapeState(i);
auto deformerIndex = self->_modelMeshRenderItemShapes[i].deformerIndex;
bool isDeformed = (deformerIndex != hfm::UNDEFINED_KEY);
auto skinDeformerIndex = shapeState._skinDeformerIndex;
bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex);
bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(shapeState._meshIndex);
if (isDeformed) {
const auto& meshState = self->getMeshState(deformerIndex);
// MeshState meshState;
if (skinDeformerIndex != hfm::UNDEFINED_KEY) {
const auto& meshState = self->getMeshState(skinDeformerIndex);
bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning();
transaction.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, shapeState, meshState, useDualQuaternionSkinning,
invalidatePayloadShapeKey, primitiveMode, renderItemKeyGlobalFlags, cauterized](ModelMeshPartPayload& data) {
if (useDualQuaternionSkinning) {
@ -303,15 +296,11 @@ void Model::reset() {
}
void Model::updateShapeStatesFromRig() {
const HFMModel& hfmModel = getHFMModel();
// TODO: should all Models have a valid _rig?
{ // Shapes state:
const auto& shapes = hfmModel.shapes;
_shapeStates.resize(shapes.size());
for (int s = 0; s < shapes.size(); ++s) {
uint32_t jointId = shapes[s].joint;
for (auto& shape : _shapeStates) {
uint32_t jointId = shape._jointIndex;
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();
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();
const HFMModel& hfmModel = getHFMModel();
const auto& hfmSkinDeformers = hfmModel.skinDeformers;
for (int i = 0; i < hfmSkinDeformers.size(); i++) {
const auto& dynT = hfmSkinDeformers[i];
@ -740,9 +739,9 @@ bool Model::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointe
render::Transaction transaction;
for (int i = 0; i < (int) _modelMeshRenderItemIDs.size(); i++) {
auto itemID = _modelMeshRenderItemIDs[i];
auto shape = _modelMeshRenderItemShapes[i];
auto& shape = _shapeStates[i];
// TODO: check to see if .partIndex matches too
if (shape.meshIndex == meshIndex) {
if (shape._meshIndex == meshIndex) {
transaction.updateItem<ModelMeshPartPayload>(itemID, [=](ModelMeshPartPayload& data) {
data.updateMeshPart(mesh, partIndex);
});
@ -904,8 +903,8 @@ void Model::updateRenderItemsKey(const render::ScenePointer& scene) {
}
auto renderItemsKey = _renderItemKeyGlobalFlags;
render::Transaction transaction;
foreach(auto item, _modelMeshRenderItemsMap.keys()) {
transaction.updateItem<ModelMeshPartPayload>(item, [renderItemsKey](ModelMeshPartPayload& data) {
for(auto itemID: _modelMeshRenderItemIDs) {
transaction.updateItem<ModelMeshPartPayload>(itemID, [renderItemsKey](ModelMeshPartPayload& data) {
data.updateKey(renderItemsKey);
});
}
@ -975,8 +974,8 @@ void Model::setCauterized(bool cauterized, const render::ScenePointer& scene) {
return;
}
render::Transaction transaction;
foreach (auto item, _modelMeshRenderItemsMap.keys()) {
transaction.updateItem<ModelMeshPartPayload>(item, [cauterized](ModelMeshPartPayload& data) {
for (auto itemID : _modelMeshRenderItemIDs) {
transaction.updateItem<ModelMeshPartPayload>(itemID, [cauterized](ModelMeshPartPayload& data) {
data.setCauterized(cauterized);
});
}
@ -1003,26 +1002,25 @@ bool Model::addToScene(const render::ScenePointer& scene,
bool somethingAdded = false;
if (_modelMeshRenderItemsMap.empty()) {
if (_modelMeshRenderItemIDs.empty()) {
bool hasTransparent = false;
size_t verticesCount = 0;
foreach(auto renderItem, _modelMeshRenderItems) {
auto item = scene->allocateID();
auto renderPayload = std::make_shared<ModelMeshPartPayload::Payload>(renderItem);
if (_modelMeshRenderItemsMap.empty() && statusGetters.size()) {
if (_modelMeshRenderItemIDs.empty() && statusGetters.size()) {
renderPayload->addStatusGetters(statusGetters);
}
transaction.resetItem(item, renderPayload);
hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent();
verticesCount += renderItem.get()->getVerticesCount();
_modelMeshRenderItemsMap.insert(item, renderPayload);
_modelMeshRenderItemIDs.emplace_back(item);
}
somethingAdded = !_modelMeshRenderItemsMap.empty();
somethingAdded = !_modelMeshRenderItemIDs.empty();
_renderInfoVertexCount = verticesCount;
_renderInfoDrawCalls = _modelMeshRenderItemsMap.count();
_renderInfoDrawCalls = (uint32_t) _modelMeshRenderItemIDs.size();
_renderInfoHasTransparent = hasTransparent;
}
@ -1037,14 +1035,12 @@ bool Model::addToScene(const render::ScenePointer& scene,
}
void Model::removeFromScene(const render::ScenePointer& scene, render::Transaction& transaction) {
foreach (auto item, _modelMeshRenderItemsMap.keys()) {
transaction.removeItem(item);
for (auto itemID: _modelMeshRenderItemIDs) {
transaction.removeItem(itemID);
}
_modelMeshRenderItemIDs.clear();
_modelMeshRenderItemsMap.clear();
_modelMeshRenderItems.clear();
_modelMeshMaterialNames.clear();
_modelMeshRenderItemShapes.clear();
_priorityMap.clear();
_addedToScene = false;
@ -1415,25 +1411,22 @@ void Model::updateClusterMatrices() {
updateShapeStatesFromRig();
_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++) {
const auto& cluster = deformer.clusters[clusterIndex];
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex);
for (int skinDeformerIndex = 0; skinDeformerIndex < (int)_meshStates.size(); skinDeformerIndex++) {
MeshState& state = _meshStates[skinDeformerIndex];
auto numClusters = state.getNumClusters();
for (uint32_t clusterIndex = 0; clusterIndex < numClusters; clusterIndex++) {
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(skinDeformerIndex, clusterIndex);
if (_useDualQuaternionSkinning) {
auto jointPose = _rig.getJointPose(cluster.jointIndex);
auto jointPose = _rig.getJointPose(cbmov.jointIndex);
Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans());
Transform clusterTransform;
Transform::mult(clusterTransform, jointTransform, cbmov.inverseBindTransform);
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]);
}
}
@ -1441,7 +1434,7 @@ void Model::updateClusterMatrices() {
// post the blender if we're not currently waiting for one to finish
auto modelBlender = DependencyManager::get<ModelBlender>();
if (modelBlender->shouldComputeBlendshapes() && hfmModel.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
if (modelBlender->shouldComputeBlendshapes() && getHFMModel().hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
_blendedBlendshapeCoefficients = _blendshapeCoefficients;
modelBlender->noteRequiresBlend(getThisPointer());
}
@ -1490,7 +1483,6 @@ void Model::createRenderItemSet() {
_modelMeshRenderItems.clear();
_modelMeshMaterialNames.clear();
_modelMeshRenderItemShapes.clear();
Transform transform;
transform.setTranslation(_translation);
@ -1510,12 +1502,11 @@ void Model::createRenderItemSet() {
auto material = getNetworkModel()->getShapeMaterial(shapeID);
_modelMeshMaterialNames.push_back(material ? material->getName() : "");
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)shape.mesh, shape.skinDeformer });
}
}
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) {
@ -1571,11 +1562,11 @@ void Model::applyMaterialMapping() {
PrimitiveMode primitiveMode = getPrimitiveMode();
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
auto modelMeshRenderItemIDs = _modelMeshRenderItemIDs;
auto modelMeshRenderItemShapes = _modelMeshRenderItemShapes;
auto shapeStates = _shapeStates;
std::unordered_map<int, bool> shouldInvalidatePayloadShapeKeyMap;
for (auto& shape : _modelMeshRenderItemShapes) {
shouldInvalidatePayloadShapeKeyMap[shape.meshIndex] = shouldInvalidatePayloadShapeKey(shape.meshIndex);
for (auto& shape : _shapeStates) {
shouldInvalidatePayloadShapeKeyMap[shape._meshIndex] = shouldInvalidatePayloadShapeKey(shape._meshIndex);
}
auto& materialMapping = getMaterialMapping();
@ -1598,7 +1589,7 @@ void Model::applyMaterialMapping() {
std::weak_ptr<Model> weakSelf = shared_from_this();
auto materialLoaded = [networkMaterialResource, shapeIDs, priorityMapPerResource, renderItemsKey, primitiveMode, useDualQuaternionSkinning,
modelMeshRenderItemIDs, modelMeshRenderItemShapes, shouldInvalidatePayloadShapeKeyMap, weakSelf]() {
modelMeshRenderItemIDs, shapeStates, shouldInvalidatePayloadShapeKeyMap, weakSelf]() {
std::shared_ptr<Model> self = weakSelf.lock();
if (!self || networkMaterialResource->isFailed() || networkMaterialResource->parsedMaterials.names.size() == 0) {
return;
@ -1624,7 +1615,7 @@ void Model::applyMaterialMapping() {
for (auto shapeID : shapeIDs) {
if (shapeID < modelMeshRenderItemIDs.size()) {
auto itemID = modelMeshRenderItemIDs[shapeID];
auto meshIndex = modelMeshRenderItemShapes[shapeID].meshIndex;
auto meshIndex = shapeStates[shapeID]._meshIndex;
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKeyMap.at(meshIndex);
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) {
if (shapeID < _modelMeshRenderItemIDs.size()) {
auto itemID = _modelMeshRenderItemIDs[shapeID];
auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex;
auto meshIndex = _shapeStates[shapeID]._meshIndex;
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, renderItemsKey,
invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning](ModelMeshPartPayload& data) {
@ -1684,7 +1675,7 @@ void Model::removeMaterial(graphics::MaterialPointer material, const std::string
auto itemID = _modelMeshRenderItemIDs[shapeID];
auto renderItemsKey = _renderItemKeyGlobalFlags;
PrimitiveMode primitiveMode = getPrimitiveMode();
auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex;
auto meshIndex = _shapeStates[shapeID]._meshIndex;
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, renderItemsKey,

View file

@ -297,6 +297,16 @@ public:
int getRenderInfoDrawCalls() const { return _renderInfoDrawCalls; }
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 {
public:
TransformDualQuaternion() {}
@ -339,18 +349,13 @@ public:
public:
std::vector<TransformDualQuaternion> clusterDualQuaternions;
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); }
class ShapeState {
public:
glm::mat4 _rootFromJointTransform;
};
const ShapeState& getShapeState(int index) { return _shapeStates.at(index); }
uint32_t getGeometryCounter() const { return _deleteGeometryCounter; }
const QMap<render::ItemID, render::PayloadPointer>& getRenderItems() const { return _modelMeshRenderItemsMap; }
BlendShapeOperator getModelBlendshapeOperator() const { return _modelBlendshapeOperator; }
void renderDebugMeshBoxes(gpu::Batch& batch, bool forward);
@ -425,10 +430,12 @@ protected:
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
std::vector<MeshState> _meshStates;
std::vector<ShapeState> _shapeStates;
void updateShapeStatesFromRig();
std::vector<MeshState> _meshStates;
virtual void initJointStates();
void setScaleInternal(const glm::vec3& scale);
@ -471,10 +478,7 @@ protected:
static AbstractViewStateInterface* _viewState;
QVector<std::shared_ptr<ModelMeshPartPayload>> _modelMeshRenderItems;
QMap<render::ItemID, render::PayloadPointer> _modelMeshRenderItemsMap;
render::ItemIDs _modelMeshRenderItemIDs;
using ShapeInfo = struct { int meshIndex; uint32_t deformerIndex{ hfm::UNDEFINED_KEY }; };
std::vector<ShapeInfo> _modelMeshRenderItemShapes;
std::vector<std::string> _modelMeshMaterialNames;
bool _addedToScene { false }; // has been added to scene

View file

@ -41,37 +41,37 @@ void SoftAttachmentModel::updateClusterMatrices() {
_needsUpdateClusterMatrices = false;
const HFMModel& hfmModel = getHFMModel();
for (int i = 0; i < (int) _meshStates.size(); i++) {
MeshState& state = _meshStates[i];
const HFMMesh& mesh = hfmModel.meshes.at(i);
int meshIndex = i;
for (int j = 0; j < mesh.clusters.size(); j++) {
const HFMCluster& cluster = mesh.clusters.at(j);
for (int skinDeformerIndex = 0; skinDeformerIndex < (int)_meshStates.size(); skinDeformerIndex++) {
MeshState& state = _meshStates[skinDeformerIndex];
auto numClusters = state.getNumClusters();
for (uint32_t clusterIndex = 0; clusterIndex < numClusters; clusterIndex++) {
const auto& cbmov = _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(skinDeformerIndex, clusterIndex);
int clusterIndex = j;
// TODO: cache these look-ups as an optimization
int jointIndexOverride = getJointIndexOverride(cluster.jointIndex);
glm::mat4 jointMatrix;
int jointIndexOverride = getJointIndexOverride(cbmov.jointIndex);
auto rig = &_rigOverride;
if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) {
jointMatrix = _rigOverride.getJointTransform(jointIndexOverride);
} else {
jointMatrix = _rig.getJointTransform(cluster.jointIndex);
rig = &_rig;
}
if (_useDualQuaternionSkinning) {
glm::mat4 m;
glm_mat4u_mul(jointMatrix, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindMatrix, m);
state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(m);
} else {
glm_mat4u_mul(jointMatrix, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindMatrix, state.clusterMatrices[j]);
auto jointPose = rig->getJointPose(cbmov.jointIndex);
Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans());
Transform clusterTransform;
Transform::mult(clusterTransform, jointTransform, cbmov.inverseBindTransform);
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
auto modelBlender = DependencyManager::get<ModelBlender>();
if (modelBlender->shouldComputeBlendshapes() && hfmModel.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
if (modelBlender->shouldComputeBlendshapes() && getHFMModel().hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) {
_blendedBlendshapeCoefficients = _blendshapeCoefficients;
modelBlender->noteRequiresBlend(getThisPointer());
}

View file

@ -348,7 +348,7 @@ bool vhacd::VHACDUtil::computeVHACD(HFMModel& hfmModel,
if (_verbose) {
qDebug() << "mesh" << meshIndex << ": "
<< " parts =" << mesh.parts.size() << " clusters =" << mesh.clusters.size()
<< " parts =" << mesh.parts.size()
<< " vertices =" << numVertices;
}
++meshIndex;