mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 19:13:38 +02:00
Merge pull request #16377 from samcake/instancing
Instancing: Clean ups, simpler Skin Cluster(s) updates
This commit is contained in:
commit
68e39eee2e
14 changed files with 131 additions and 192 deletions
|
@ -34,8 +34,7 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) {
|
|||
const auto& defor = hfmModel.skinDeformers[i];
|
||||
std::vector<HFMCluster> dummyClustersList;
|
||||
|
||||
for (int j = 0; j < defor.clusters.size(); j++) {
|
||||
std::vector<glm::mat4> bindMatrices;
|
||||
for (int j = 0; j < (uint32_t) defor.clusters.size(); j++) {
|
||||
// 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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1009,7 +1009,7 @@ HFMModel::Pointer OBJSerializer::read(const hifi::ByteArray& data, const hifi::V
|
|||
}
|
||||
|
||||
// GO over the shapes once more to assign hte material index correctly
|
||||
for (int i = 0; i < hfmModel.shapes.size(); ++i) {
|
||||
for (int i = 0; i < (uint32_t) hfmModel.shapes.size(); ++i) {
|
||||
auto foundMaterialIndex = materialNameToIndex.find(materialNamePerShape[i]);
|
||||
if (foundMaterialIndex != materialNameToIndex.end()) {
|
||||
hfmModel.shapes[i].material = foundMaterialIndex.value();
|
||||
|
|
|
@ -386,6 +386,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;
|
||||
|
|
|
@ -491,8 +491,8 @@ bool NetworkModel::areTexturesLoaded() const {
|
|||
}
|
||||
|
||||
const std::shared_ptr<NetworkMaterial> NetworkModel::getShapeMaterial(int shapeID) const {
|
||||
auto materialID = getHFMModel().shapes[shapeID].material;
|
||||
if ((materialID >= 0) && (materialID < (int)_materials.size())) {
|
||||
uint32_t materialID = getHFMModel().shapes[shapeID].material;
|
||||
if (materialID < (uint32_t)_materials.size()) {
|
||||
return _materials[materialID];
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
@ -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 < (int) _meshStates.size(); ++i) {
|
||||
_cauterizeMeshStates[i] = _meshStates[i];
|
||||
}
|
||||
}
|
||||
return needsFullUpdate;
|
||||
|
@ -49,15 +45,12 @@ bool CauterizedModel::updateGeometry() {
|
|||
void CauterizedModel::createRenderItemSet() {
|
||||
if (_isCauterized) {
|
||||
assert(isLoaded());
|
||||
const auto& meshes = _renderGeometry->getMeshes();
|
||||
|
||||
|
||||
// We should not have any existing renderItems if we enter this section of code
|
||||
Q_ASSERT(_modelMeshRenderItems.isEmpty());
|
||||
|
||||
_modelMeshRenderItems.clear();
|
||||
_modelMeshMaterialNames.clear();
|
||||
_modelMeshRenderItemShapes.clear();
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(_translation);
|
||||
|
@ -72,14 +65,13 @@ void CauterizedModel::createRenderItemSet() {
|
|||
// Run through all of the meshes, and place them into their segregated, but unsorted buckets
|
||||
int shapeID = 0;
|
||||
const auto& shapes = _renderGeometry->getHFMModel().shapes;
|
||||
for (shapeID; shapeID < shapes.size(); shapeID++) {
|
||||
for (shapeID; shapeID < (int) shapes.size(); shapeID++) {
|
||||
const auto& shape = shapes[shapeID];
|
||||
|
||||
_modelMeshRenderItems << std::make_shared<CauterizedMeshPartPayload>(shared_from_this(), shape.mesh, shape.meshPart, shapeID, transform);
|
||||
|
||||
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 +89,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 +113,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 +122,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 < (int) _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 +153,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 +193,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,
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
|
|
@ -210,11 +210,8 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in
|
|||
assert(shape.mesh == meshIndex);
|
||||
assert(shape.meshPart == partIndex);
|
||||
|
||||
bool useDualQuaternionSkinning = model->getUseDualQuaternionSkinning();
|
||||
|
||||
auto& modelMesh = model->getNetworkModel()->getMeshes().at(_meshIndex);
|
||||
_meshNumVertices = (int)modelMesh->getNumVertices();
|
||||
// const Model::MeshState& state = model->getMeshState(_meshIndex);
|
||||
|
||||
updateMeshPart(modelMesh, partIndex);
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ public:
|
|||
|
||||
int _meshIndex;
|
||||
int _shapeID;
|
||||
int _deformerIndex;
|
||||
uint32_t _deformerIndex;
|
||||
|
||||
bool _isSkinned{ false };
|
||||
bool _isBlendShaped { false };
|
||||
|
|
|
@ -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,11 +320,21 @@ bool Model::updateGeometry() {
|
|||
initJointStates();
|
||||
assert(_meshStates.empty());
|
||||
|
||||
const HFMModel& hfmModel = getHFMModel();
|
||||
|
||||
const auto& shapes = hfmModel.shapes;
|
||||
_shapeStates.resize(shapes.size());
|
||||
for (uint32_t s = 0; s < (uint32_t) 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++) {
|
||||
for (uint32_t i = 0; i < (uint32_t) hfmSkinDeformers.size(); i++) {
|
||||
const auto& dynT = hfmSkinDeformers[i];
|
||||
MeshState state;
|
||||
state.clusterDualQuaternions.resize(dynT.clusters.size());
|
||||
|
@ -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 == (uint32_t) 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,21 @@ 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);
|
||||
auto jointMatrix = _rig.getJointTransform(cbmov.jointIndex);
|
||||
glm_mat4u_mul(jointMatrix, cbmov.inverseBindMatrix, state.clusterMatrices[clusterIndex]);
|
||||
}
|
||||
}
|
||||
|
@ -1441,7 +1433,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());
|
||||
}
|
||||
|
@ -1483,14 +1475,12 @@ const render::ItemIDs& Model::fetchRenderItemIDs() const {
|
|||
|
||||
void Model::createRenderItemSet() {
|
||||
assert(isLoaded());
|
||||
const auto& meshes = _renderGeometry->getMeshes();
|
||||
|
||||
// We should not have any existing renderItems if we enter this section of code
|
||||
Q_ASSERT(_modelMeshRenderItems.isEmpty());
|
||||
|
||||
_modelMeshRenderItems.clear();
|
||||
_modelMeshMaterialNames.clear();
|
||||
_modelMeshRenderItemShapes.clear();
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(_translation);
|
||||
|
@ -1501,21 +1491,19 @@ void Model::createRenderItemSet() {
|
|||
offset.postTranslate(_offset);
|
||||
|
||||
// Run through all of the meshes, and place them into their segregated, but unsorted buckets
|
||||
int shapeID = 0;
|
||||
const auto& shapes = _renderGeometry->getHFMModel().shapes;
|
||||
for (shapeID; shapeID < shapes.size(); shapeID++) {
|
||||
for (uint32_t shapeID = 0; shapeID < shapes.size(); shapeID++) {
|
||||
const auto& shape = shapes[shapeID];
|
||||
|
||||
_modelMeshRenderItems << std::make_shared<ModelMeshPartPayload>(shared_from_this(), shape.mesh, shape.meshPart, shapeID, transform);
|
||||
|
||||
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 +1559,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 +1586,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 +1612,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 +1650,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 +1672,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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue